呈现视图控制器而不更改状态栏颜色,如UIAlertController

在执行一些networking操作时,我提出了一个模式视图控制器(类似于MBProgressHUD,但是作为视图控制器),以防止用户交互并指示进度。

视图控制器具有modalPresentationStyle = .Custom并使用转换委托和自定义表示控制器进行animation处理。 除了animation过渡之外,他们没有自定义操作来驱动演示文稿。

我有的问题是,无论何时呈现视图控制器,它将状态栏颜色黑色。 我可以重写preferredStatusBarStyle ,使其始终返回.LightContent但有时这个视图控制器是通过一个视图控制器与.Default呈现,我不想在那里改变它。 基本上,我想拥有与UIAlertController相同的行为。

屏幕截图显示呈现的视图控制器导致黑暗状态栏的内容

我已经尝试configuration演示文稿控制器以将呈现的视图控制器移出状态栏空间:

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

这些设置确实将所呈现的控制器的顶部移出状态栏,但状态栏仍然受到影响。 有没有一个财产我缺less,将停止我的视图控制器更新状态栏的风格?

更新

看起来这已经在iOS 10中修复了。默认行为是忽略呈现的视图控制器中的状态栏规则, 除非呈现的视图控制器具有modalPresentationCapturesStatusBarAppearance == true或者您使用了几个内置的演示控制器之一进入状态栏空间(不是.custom )。

基本上,自定义的行为已经改变为默认select退出而不是强制select。


对于iOS 9.x及更低版本

大量挖掘之后,设置应用程序状态栏颜色的内部逻辑如下所示:

 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() 

视图控制器的属性_presentedStatusBarViewController是基于演示控制器的私有方法_shouldChangeStatusBarViewController()的值在演示期间分配的。 此方法的默认实现是返回true,使用_UIAlertControllerPresentationController和一些其他呈现控制器返回false。

这意味着不改变状态栏的最直接的方法是简单地将此方法添加到我的演示文稿控制器:

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

不幸的是,这不会通过App Store审查。

相反,我正在做的是重新创build应用于我的视图控制器呈现视图控制器的逻辑:

 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() } }