SwiftUI in iOS14: drawingGroup() and Mask have broken behaviour

In the first iOS14 beta, the following code does not work anymore when drawingGroup() is called:

Code Block
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
  var body: some View {
    MaskView().frame(width:300, height: 50)
  }
}
struct MaskView: View {
  var ratio: CGFloat = 0.3
   
  var body: some View {
    GeometryReader { g in
      ZStack {
        LeftView()
          .mask(Rectangle()
              .padding(.trailing, (1-self.ratio) * g.size.width))
        RightView()
          .mask(Rectangle()
              .padding(.leading, self.ratio * g.size.width))
      }
    }
  }
}
struct LeftView: View {
  var body: some View {
    Rectangle().fill(
      LinearGradient(
        gradient: Gradient(colors: [.black, .white]),
        startPoint: .leading,
        endPoint: .trailing)
    )
    .drawingGroup()
  }
}
struct RightView: View {
  var body: some View {
    Rectangle().fill(
       
        LinearGradient(
          gradient: Gradient(colors: [.white, .black]),
          startPoint: .leading,
          endPoint: .trailing)
    )
    .drawingGroup()
  }
}
PlaygroundPage.current.setLiveView(ContentView())


Without drawingGroup(), this code displays on both iOS13 and 14 a gradient from black to white (0-30% of it), as well as a gradient from white to black (30%-100%), right next to each other.

On iOS13 and 14, when enabling drawingGroup(), the gradient in the Playground changes from black->white to white->yellow (for the left view, and equivalently for the right view). This is the first weird behaviour I observed.

On iOS14 only, calling drawingGroup() breaks the .padding() calculation. I can fix this as follows, which works on both iOS13 and 14:

Code Block
   var body: some View {
    GeometryReader { g in
      ZStack {
        LeftView()
          .mask(Rectangle()
              .padding(.trailing, (1-self.ratio) * g.size.width))
        RightView()
          .mask(Rectangle()
              .frame(width: g.size.width)
              .padding(.leading, self.ratio * g.size.width))
      }
    }
  }


Note that calling .frame(width: g.size.width) only works on RightView, on LeftView, I can either omit this call, or I need to call .frame(width: self.ratio * g.size.width). Which I absolutely don't understand. It would make sense to call .frame(width: (1-ratio) * g.size.width) on RightView, but that leads to the broken behaviour again.


It seems to me that in iOS14, for drawing groups, left padding is included in the frame width, whereas right padding is not. in iOS13, left padding is also not included in the frame width.

If that is the case, it seems like a regression in iOS14 to me.
Hi, thanks for reporting this — we've fixed the layout (padding) bug, it should show up in a future seed build.

On iOS13 and 14, when enabling drawingGroup(), the gradient in the Playground changes from black->white to white->yellow (for the left view, and equivalently for the right view). This is the first weird behaviour I observed.

I'm not seeing this part though, what kind of hardware are you running the test on?

Thanks for the update, glad you fixed the padding bug.

Regarding the drawingGroup(): I'm running this on a playground on Xcode 11.5 or the current (first) Xcode 12 beta. See below for screenshots:

With drawingGroup: https://www.dropbox.com/s/w2xec3a35r1ggvf/Screenshot%202020-07-01%20at%2014.12.27.png?dl=0
Without drawingGroup: https://www.dropbox.com/s/mg4hl2amb94u9df/Screenshot%202020-07-01%20at%2014.12.36.png?dl=0

This seems to be specific to LinearGradient; it doesn't happen with something like Color.red, and also doesn't happen with the subview (a Path with a solid colour) that I'm masking in the actual app I'm developing.
I've tried this on a couple of different macs, but haven't been able to see the yellow gradient. Could you file a feedback item including the hardware configuration of your mac (the GPU type is the most important part) so we can investigate this further? thanks.

Sure thing, just done that.
I'm also seeing issues with mask in the latest beta that didn't happen on beta 1.

My code:

Code Block
import SwiftUI
struct ContentView: View {
var dollarFill: some View {
LinearGradient(
gradient: Gradient(colors: [
Color.green,
Color.blue
]),
startPoint: .top,
endPoint: .bottom
)
.cornerRadius(10)
}
var dollarFillPercent: CGFloat = 0.7
var body: some View {
GeometryReader { gr in
ZStack {
self.dollarFill
.mask(ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 10)
.frame(width: gr.size.width * self.dollarFillPercent)
RoundedRectangle(cornerRadius: 10)
.strokeBorder(style: StrokeStyle(lineWidth: 1.0, dash: [5]))
})
}
}.aspectRatio(CGFloat(2.25), contentMode: .fit)
}
}


The forum won't let me post screenshots, but basically what I see on beta 1 is a 70% "filled in" rectangle. In beta 2, this rectangle is 100% filled in no matter what dollarFillPercent is set to.

May not be the same issue as OP, but sounded potentially related?
SwiftUI in iOS14: drawingGroup() and Mask have broken behaviour
 
 
Q