A view controller view without changing the color of the status bar, for example, UIAlertController

In some network operations, I present a modal view controller (similar to MBProgressHUD, but as a view controller) to prevent user interaction and indicate progress.

The presentation controller has modalPresentationStyle = .Custom and is animated using a transition delegate and a custom presentation controller. In addition to animation transitions, they do not have special actions leading the presentation.

The problem is that whenever a view controller is presented, it turns the dash into a status bar. I could override preferredStatusBarStyle to always return .LightContent , but sometimes this view controller is represented on the view controller using .Default , and I also don't want to change it. Basically, I want to have the same behavior as UIAlertController .

Screenshot showing presented view controller causing dark status bar content

I tried to configure the view controller to move the presented view controller from the status bar space:

 private class SEUIProgressControllerPresentationController: UIPresentationController { override func shouldPresentInFullscreen() -> Bool { return false } private override func frameOfPresentedViewInContainerView() -> CGRect { return super.frameOfPresentedViewInContainerView().insetBy(dx: 40, dy: 100) } ... } 

These settings move the top of the presented controller from the status bar, but the status bar is still affected. Is there a property that I am missing that will stop my view controller from updating the status bar style?

+5
source share
1 answer

Update

It looks like this was fixed in iOS 10. The default behavior is to ignore the status bar rules from the presented view controller, unless the presented view controller has modalPresentationCapturesStatusBarAppearance == true or you use one of several built-in view controllers that propagate into the status bar space ( not .custom ).

Basically, the behavior for custom has been changed to default failure, not forced failure.


For iOS 9.x and below

After repeated copying, the internal logic for setting the color of the application status bar is as follows:

 var viewController = window.rootViewController! while let presentedViewController = viewController.valueForKey("_presentedStatusBarViewController") as? UIViewController { viewController = presentedViewController } while let childViewController = viewController.childViewControllerForStatusBarStyle() { viewController = childViewController } let style = viewController.preferredStatusBarStyle() 

The presentation manager property _presentedStatusBarViewController is assigned during presentation based on the value of its private control method _shouldChangeStatusBarViewController() . The default implementation of this method is to return true with _UIAlertControllerPresentationController and several other view controllers that return false.

This means that the most direct way to not change this status bar is to simply add this method to my view controller:

 private class SEUIProgressControllerPresentationController: UIPresentationController { @objc func _shouldChangeStatusBarViewController() -> Bool { return false } ... } 

Unfortunately, this will not pass the review of the App Store.

Instead of what I am doing, this is a recreation of the logic that will be applied to the view controller in my view controller:

 public class SEUIProgressController: UIViewController { ... public override func preferredStatusBarStyle() -> UIStatusBarStyle { guard var targetViewController = presentingViewController else { return .LightContent } while let parentViewController = targetViewController.parentViewController { targetViewController = parentViewController } while let childViewController = targetViewController.childViewControllerForStatusBarStyle() { targetViewController = childViewController } return targetViewController.preferredStatusBarStyle() } public override func prefersStatusBarHidden() -> Bool { guard var targetViewController = presentingViewController else { return false } while let parentViewController = targetViewController.parentViewController { targetViewController = parentViewController } while let childViewController = targetViewController.childViewControllerForStatusBarHidden() { targetViewController = childViewController } return targetViewController.prefersStatusBarHidden() } } 
+3
source

Source: https://habr.com/ru/post/1240723/


All Articles