当拆分视图控制器的显示模式发生变化时,我需要能够更新我的应用程序的UI。具体来说,如果它从扩展界面变为折叠界面,我需要做一些事情,如果它从折叠变为扩展。
我目前通过traitCollectionDidChange
处理此问题,虽然这对我的两个分割视图控制器似乎有效,但第三个不能正常工作。看起来这个方法过早被调用,所以当我检查displayMode
以查看它是否UISplitViewcontrollerDisplayModeAllVisible
时,拆分视图还没有更新到新的显示模式。因此它最终会删除我想要添加的按钮,或者在我想删除它们时添加它们。如果我在0.1秒之后延迟检查显示模式,displayMode
值将正确表示旋转完成时的状态以及采取的相应操作。
我的问题是,有没有更好的方法来更新我的应用的用户界面,也许有办法知道displayMode
何时发生变化?我不想冒太大的风险,但我也不想等到轮换完成以更新用户界面。延迟检查是一个非常脆弱的解决方案,可能很容易导致意外行为,有时它可能无法正常工作。
答案 0 :(得分:2)
遇到类似问题,并在UISplitViewControllerDelegate
上发现了此委托方法func targetDisplayModeForActionInSplitViewController(svc: UISplitViewController) -> UISplitViewControllerDisplayMode
唯一的问题是,当你问svc.displayMode时,它会告诉你它来自哪个模式而不是它的去向。但是,它足以阻止UISplitViewController进入特定状态。
func targetDisplayModeForActionInSplitViewController(svc: UISplitViewController) -> UISplitViewControllerDisplayMode {
switch svc.displayMode {
case .PrimaryOverlay :
return .AllVisible
case .AllVisible :
return .PrimaryHidden
case .PrimaryHidden :
return .AllVisible
case .Automatic :
return .AllVisible
default:
return .AllVisible
}
}
我能够用来知道我的UISplitViewController显示模式何时改变的另一个委托方法是
func splitViewController(svc: UISplitViewController, willChangeToDisplayMode displayMode: UISplitViewControllerDisplayMode)
然后,如果您处理对您来说重要的状态,则可以相应地更改视图
func splitViewController(svc: UISplitViewController, willChangeToDisplayMode displayMode: UISplitViewControllerDisplayMode) {
println("will change to display mode \(displayMode.rawValue)")
if (displayMode == UISplitViewControllerDisplayMode.AllVisible) {
//do something because EVERYTHING is visible
} else if (displayMode == UISplitViewControllerDisplayMode.PrimaryHidden) {
//something else because the primary is GONE
} else if (self.splitViewController?.displayMode == UISplitViewControllerDisplayMode.PrimaryOverlay){
//handle primary overlay change
}
}
答案 1 :(得分:1)
更强大的解决方案是在primaryViewControllerForCollapsingSplitViewController:
中使用primaryViewControllerForExpandingSplitViewController:
和UISplitViewControllerDelegate
。
从文档中说出
如果您没有实现此方法,或者您的实现 返回nil,拆分视图控制器选择其主视图 控制器作为显示器。
因此,请实施这些方法来跟踪折叠和展开,然后返回nil
,您仍然会获得默认行为。
答案 2 :(得分:0)
如果UISplitViewController:preferredDisplayMode
为UISplitViewControllerDisplayModeAutomatic
,则其代表的targetDisplayModeForActionInSplitViewController:
方法可让您从displayMode
后检索UISplitViewController
改变它的动作 - 例如displayModeButtonItem
,滑动手势,旋转等。检索到的displayMode
将不是UISplitViewControllerDisplayModeAutomatic
- 它将反映实际的主要/次要显示状态
根据bolnad推断,targetDisplayModeForActionInSplitViewController:
委托方法是为了指定displayMode
在NEXT操作中使用的UISplitViewController
(“它在哪里”) ,不需要很快。
在我的使用中,由于我的UISplitViewController.preferredDisplayMode
始终为UISplitViewControllerDisplayModeAutomatic
,因此我会在displayMode
更改后触发我需要的任何活动,然后返回UISplitViewControllerDisplayModeAutomatic
以供将来使用。
答案 3 :(得分:0)
如果我在0.1秒之后延迟检查该显示模式,则displayMode值正确表示旋转完成时将采取的措施,并采取适当的措施。
您要做的只是在显示模式更改后更新UI。当您设置0.1秒延迟时,它可以正常工作。
因此,解决方案非常简单,您只需将代码放在main thread runloop
的末尾,使用GCD
// Swift3.0
DispatchQueue.main.async {
// your code here
}
这意味着您的代码将在UI/Main Thread
完成之前的工作(例如layoutSubviews,旋转或更改displayMode)后执行。如果Main/UI Thread
是RunLoop
,则设置0.1秒延迟的方法可能无法正常工作太忙了,不能在0.1秒内处理以前的工作
如果您不清楚,请参阅有关value
here