StatusBarFrame in iOS 11

Hello, getting the statusBarFrame doesn't appear to return the correct value in iOS 11. I realize there may be a nicer way of dealing with this in the future using the Safe Area but right now I really need to get the statusBarFrame to work as it did before iOS 11. Here's how I usually get it.


UIApplication.shared.statusBarFrame


I'v verified that my app works properly before iOS 11. But in iOS 11 it appears to be backwards; for example, for an iPhone in portrait it should 20 and in landscape 0. But it returns 0 in portrait and 20 in landscape.

I think it appears to be a timing issue. I wrapped the code that uses the statusBarFrame in a DispatchQueue.main.async {} closure and it works fine. I would consider this more of a bandaid. Still hoping for a proper solution.

Suggestions appreciated.


Thanks!

In the iPhone X simulator after going back from landscape to portait, in viewDidLayoutSubviews I get 44.0 for the height:


CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect statusBarRectConverted = [self.view convertRect:statusBarFrame fromView:nil];


During the transition, at least for my little test, viewDidLayoutSubviews is called three times. The first two times the height is 0.0, but the last time viewDidLayotuSubviews gets called the height is 44.0.

Where do you call statusBarFrame from?

I need to use it when the device changes orientation; so I call it from traitCollectionDidChange() as shown below:


  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    print("traitCollectionDidChange statusBarHgt \(UIApplication.shared.statusBarFrame)")    
   refreshDisplay()
 }


I've changed it to this and the frame has the correct value inside the DispatchQueue.main.async{} closure:


  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    print("traitCollectionDidChange statusBarHgt \(UIApplication.shared.statusBarFrame)")
    DispatchQueue.main.async { [weak self] in
      print("DispatchQueue.main.async statusBarHgt \(UIApplication.shared.statusBarFrame)")
      self.refreshDisplay()
    }
}


Any suggestions?

I'd expect the statusBarFrame to be updated before traitCollectionDidChange. Maybe you should file a bug (if you haven't aleady).


Is the statusBarFrame wrong in viewDidLayoutSubviews too?

Yeah, I just tried and it's the same problem in viewDidLayoutSubviews() . I haven't filed a bug report yet. I want to do some more checking. All this has been in an app that I'm updating for iOS 11. I want to create a simple app to just check this issue and if it also happens on that then I'll file a bug report. Otherwise, it could be something that my app is, unintentionally, doing. I have no idea how an app could influence something in UIApplication.shared but, at this stage, I'm not ruling anything out.


Thanks.

Accepted Answer

In the iPhone X simulator after going back from landscape to portait, in viewDidLayoutSubviews I get 44.0 for the height:


CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect statusBarRectConverted = [self.view convertRect:statusBarFrame fromView:nil];


During the transition, at least for my little test, viewDidLayoutSubviews is called three times. The first two times the height is 0.0, but the last time viewDidLayotuSubviews gets called the height is 44.0.

Hi,

I just had a chane to get back into this and I see the same thing you wrote on 10/8: the status bar frame has the correct value on the last call to viewDidLayoutSubviews().

Thanks.

StatusBarFrame in iOS 11
 
 
Q