1

I use this code to get the screen width and height

public var width: CGFloat {
    return UIScreen.main.bounds.width
}

public var height: CGFloat {
    return UIScreen.main.bounds.height
}

After a rotation the code is working fine but if I start the app in Landscape mode, the returned height in viewDidLoad is wrong and is 812.0, which is the width. If I rotate to portrait and than back to landscape, than the value is 375.0 which is right.

TonyStark4ever
  • 848
  • 1
  • 9
  • 24
mbbf
  • 21
  • 3

1 Answers1

2

According to this answer, you should run your code in viewWillAppear and/or viewDidLayoutSubviews. When viewDidLoad is called, that view controller's view is guaranteed to be loaded into memory, but it is not yet rendered. viewWillAppear is called when a view is about to be added to an on-screen view hierarchy, as detailed in the Apple developer documentation. At this point, the view controller should be able to access the orientation that the device is in, since its content views will most likely be rendered when viewWillAppear is called. If your code is still returning the wrong values, you may need to move it into viewDidLayoutSubviews, which is called whenever the bounds of the current view will change.

Edit: it looks like you will need to flip the width and height values based on the orientation and their relationship to one another, as stated in this answer, although that is in Objective-C. In Swift:

public var width: CGFloat {
    //If in landscape mode
    if (UIApplication.shared.statusBarOrientation.isLandscape) {
        //If in landscape and the width is less than the height (wrong),
        //return the height instead of the width 
        if (UIScreen.main.bounds.width < UIScreen.main.bounds.height) {
            return UIScreen.main.bounds.height
        }
    }
    //Else just return the width
    return UIScreen.main.bounds.width
}

public var height: CGFloat {
    //If in landscape mode
    if (UIApplication.shared.statusBarOrientation.isLandscape) {
        //If in landscape and the height is greater than the width (wrong),
        //return the width instead of the height 
        if (UIScreen.main.bounds.height > UIScreen.main.bounds.width) {
            return UIScreen.main.bounds.width
        }
    }
    //Else just return the height
    return UIScreen.main.bounds.height
}
TonyStark4ever
  • 848
  • 1
  • 9
  • 24
  • I tried in both viewWillAppear and viewDidLayoutSubviews and I still have the same problem. I have to rotate the device to portrait and then back to landscape to get the right height value – mbbf Aug 10 '20 at 08:31
  • Thank you. I though about implementing something similar but I would like to understand what is causing the problem, and if there is a cleaner way to fix that – mbbf Aug 10 '20 at 08:56
  • @mbbf I'm really not sure as to what is causing this. According to the documentation for UIScreen.main.bounds, (https://developer.apple.com/documentation/uikit/uiscreen/1617838-bounds) , "This rectangle is specified in the current coordinate space, which takes into account any interface rotations in effect for the device." Is this happening in the simulator, on a physical iOS device, or both? – TonyStark4ever Aug 10 '20 at 09:00
  • Not tried in simulator, tried it only on physical iOS device – mbbf Aug 10 '20 at 09:03
  • @mbbf The simulator tends to be buggy with device orientation stuff, but if it's not working on a real iOS device, then there's definitely a bug somewhere. It looks like this is related to how iOS handles launching apps in landscape according to this answer (https://stackoverflow.com/questions/2664980/uiscreen-applicationframe-returning-incorrect-rectangle-on-landscape-application). The workarounds suggested there are very similar to mine. – TonyStark4ever Aug 10 '20 at 09:06