SwiftUI DIY rotate preview not working properly

Viewed 428

I recently switched from Storyboard to SwiftUI and I am having a hard time trying to preview my work. My target is an iPad Air 3rd Gen which only accepts landscape mode.

As mentionned here, it is not currently supported in XCode. Some people suggests that you can fix the size of the preview to simulate a rotation. However it does not render the same, the outlets looks too small compared to the original device.

Here is my example with an iPad Air 3rd gen which is 2224 x 1668 pixels

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().rotationEffect(Angle(degrees: 90)) // to simulate the rotation on device
    }
}

Preview1


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().previewLayout(.fixed(width: 2224, height: 1668)) // To simulate device size
    }
}

Preview2

As you can see the two previews does not match and the result on the simulator is conform to the first preview with rotationEffect, but it forces me to tilt my head each time I want to see my preview.

Is there another way to DIY a rotation in SwiftUI ?

1 Answers

I think I know what is happening here. I didnt take the Scale factor into account.

Just like in the Assets.xcasset, you can define a scale factor for images (@1x @2x @3x), it looks like preview does the same: when you fix the size of the preview it automatically assumes that the factor is @1x.

Example with an iPhone XS Max - size 1242 x 2688 & scale factor @3x:

   ContentView().previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))

Preview1

   // Raw size of an iPhone XS Max
   ContentView().previewLayout(.fixed(width: 1242, height: 2688))

Preview2

   // Scale factor taken into account
   ContentView().previewLayout(.fixed(width: 1242/3, height: 2688/3))

Preview3


All in all, this means that you do not put the actual Pixel size in a previewLayout(.fixed(...)) but the Points. Here is a Link that gives us the resolution and the scale factor for each devices.

Do not use .scaleEffect(3) on the ContentView, it just zoomes the view and the components will be out of bounds.

Finally, for iPhone 6, 6s, 7 & 8 Plus, the Native Scale factor is not the same as the UIKit Scale factor (2.608 against 3) due to downsampling. After some tests in the Preview, it seems that we have to use the UIKit Factor for better rendering.

Related