问题描述
在执行某些网络操作时,我介绍了一个模式视图控制器(类似于MBProgressHUD,但作为视图控制器),以防止用户交互并指示进度.
When performing some network operations, I present a modal view controller (similar to MBProgressHUD but as a view controller) to prevent user interaction and indicate progress.
视图控制器具有modalPresentationStyle = .Custom
,并使用过渡的委托和自定义表示控制器进行动画处理.除了为过渡设置动画外,它们没有驱动演示的自定义动作.
The view controller has modalPresentationStyle = .Custom
and is animated using a transitioning delegate and custom presentation controller. Beyond animating the transitions they have no custom actions driving the presentation.
我的问题是,只要显示了视图控制器,状态栏就会变成黑色.我可以重写preferredStatusBarStyle
使其始终返回.LightContent
,但是有时此视图控制器在具有.Default
的视图控制器上显示,并且我也不想在其中进行更改.基本上,我希望具有与UIAlertController
相同的行为.
The problem I have is that whenever the view controller is presented, it turns the status bar color black. I could override preferredStatusBarStyle
to make it always return .LightContent
but sometimes this view controller is presented over a view controller with .Default
and I don't want to change it there either. Basically, I want to have the same behavior as UIAlertController
.
我尝试配置演示文稿控制器以将演示的视图控制器移出状态栏空间:
I have tried configuring the presentation controller to move the presented view controller out of 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 do move the top of the presented controller out of the status bar but the status bar is still affected. Is there a property I am missing that would stop my view controller from updating the status bar style?
推荐答案
更新
这似乎已在iOS 10中修复.默认行为是忽略呈现的视图控制器中的状态栏规则,除非呈现的视图控制器具有modalPresentationCapturesStatusBarAppearance == true
或您使用一个扩展到状态栏空间(不是.custom
)的几个内置演示控制器中的一个.
Update
It looks like this has been fixed in iOS 10. The default behavior is to ignore the status bar rules from the presented view controller unless either the presented view controller has modalPresentationCapturesStatusBarAppearance == true
or you use one of several built-in presentation controllers that extend into the status bar space (not .custom
).
基本上,自定义行为已更改为默认选择退出,而不是强制选择加入.
Basically, the behavior for custom has changed to default opt-out rather than forced opt-in.
经过大量挖掘后,用于设置应用程序状态栏颜色的内部逻辑如下所示:
After much digging, the internal logic for setting the application's status bar color looks like this:
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.
The view controller's property _presentedStatusBarViewController
is assigned during presentation based on the value of its presentation controller's private method _shouldChangeStatusBarViewController()
. The default implementation of this method is to return true, with _UIAlertControllerPresentationController
and a handful of other presentation controllers returning false.
这意味着不更改状态栏的最直接方法就是简单地将此方法添加到我的演示控制器中:
That means the most direct way to not change that status bar is simply to add this method to my presentation controller:
private class SEUIProgressControllerPresentationController: UIPresentationController {
@objc func _shouldChangeStatusBarViewController() -> Bool {
return false
}
...
}
不幸的是,这不会通过App Store的审核.
Unfortunately, this won't pass an App Store review.
相反,我正在做的是在视图控制器中重新创建将应用于呈现视图控制器的逻辑:
Instead, what I am doing is recreating the logic that would be applied to the presenting 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()
}
}
这篇关于在不更改状态栏颜色的情况下显示视图控制器,例如UIAlertController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!