检测 UISplitViewController 何时更改显示模式
Detect when UISplitViewController changes display mode
我正在尝试使用 UISplitViewController,其中辅助控制器应该在 UISplitViewController 处于并排模式时公开 "close" 函数(通过按钮或按钮栏项),但应该隐藏其他时间的功能。我试着把它放在辅助视图控制器中:
override func viewWillAppear(_ animated: Bool) {
if splitViewController!.primaryHidden {
// hide the "close" UI artifact
} else {
// show the "close" UI artifact
}
}
这会在首次显示辅助视图时正确设置 "close" 函数的可见性,但如果 UISplitViewController 在展开和折叠之间切换(例如,通过旋转 iPhone 6s Plus),那么这个函数就不会被再次调用(这是有道理的,因为辅助控制器仍然可见)。因此,"close" 函数保持其初始状态——隐藏或显示——即使 UISplitViewController 更改模式。
如何让 "close" 函数隐藏或显示以响应 UISplitViewController 模式的变化?
好的,我找到了一个简单的解决方案。我犯了一个新手错误。诀窍是覆盖 viewWillLayoutSubviews()
而不是 viewWillAppear(animated:)
。然后一切如我所愿。似乎 viewWillLayoutSubviews()
每次包含 UISplitViewController
更改其显示模式时都会被调用(有时不止一次),而这正是我需要响应的。唯一的问题是 splitViewController
在其中一些调用中可能是 nil
,因此需要像这样实现:
override func viewWillAppear(_ animated: Bool) {
if let svc = splitViewController {
if svc.primaryHidden {
// hide the "close" UI artifact
} else {
// show the "close" UI artifact
}
}
}
作为我寻找解决方案的绊脚石的一部分,我尝试覆盖 traitCollectionDidChange(previousTraitCollection:)
。 (我尝试这个是因为我想对设备旋转做出反应。)起初我以为我在做某事,因为每当设备旋转时也会调用此函数。有趣的是(并且,令人沮丧的是)我发现调用此函数时我的视图 splitViewController
属性 是 nil
。这似乎很奇怪,因为当 UISplitViewController 重新配置自身时,viewDidDisappear(animated:)
和 viewWillAppear(animated:)
都没有被调用。但我想为什么它应该是 nil
是另一天的问题。
有 UIViewControllerShowDetailTargetDidChangeNotification
通知:
// Sometimes view controllers that are using showViewController:sender and
// showDetailViewController:sender: will need to know when the split view
// controller environment above it has changed. This notification will be
// posted when that happens (for example, when a split view controller is
// collapsing or expanding). The NSNotification's object will be the view
// controller that caused the change.
UIKIT_EXTERN NSNotificationName const UIViewControllerShowDetailTargetDidChangeNotification NS_AVAILABLE_IOS(8_0);
使用如下
- (void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showDetailTargetDidChange:) name:UIViewControllerShowDetailTargetDidChangeNotification object:self.splitViewController];
}
- (void)showDetailTargetDidChange:(NSNotification *)notification{
// changed from collapsed to expanded or vice versa
}
此 Apple 示例演示了 table 单元配件如何从纵向的披露指示器(表示将发生推送)更改为在更改为横向拆分视图时被删除:
https://developer.apple.com/library/archive/samplecode/AdaptivePhotos/Introduction/Intro.html
关于 iOS 13 beta 的注意事项,将 addObserver 与对象 nil 一起使用,因为当前存在一个错误,他们使用错误的对象发送通知。他们使用来自内部 class 集群的新 UISplitViewControllerPanelImpl 而不是 UISplitViewController 对象。
http://www.openradar.appspot.com/radar?id=4956722791710720
供日后参考:
使用 UISplitViewControllerDelegate 怎么样?
它有一个名为
的方法
splitViewController:willChangeToDisplayMode:
这应该完全符合您的要求。
我正在尝试使用 UISplitViewController,其中辅助控制器应该在 UISplitViewController 处于并排模式时公开 "close" 函数(通过按钮或按钮栏项),但应该隐藏其他时间的功能。我试着把它放在辅助视图控制器中:
override func viewWillAppear(_ animated: Bool) {
if splitViewController!.primaryHidden {
// hide the "close" UI artifact
} else {
// show the "close" UI artifact
}
}
这会在首次显示辅助视图时正确设置 "close" 函数的可见性,但如果 UISplitViewController 在展开和折叠之间切换(例如,通过旋转 iPhone 6s Plus),那么这个函数就不会被再次调用(这是有道理的,因为辅助控制器仍然可见)。因此,"close" 函数保持其初始状态——隐藏或显示——即使 UISplitViewController 更改模式。
如何让 "close" 函数隐藏或显示以响应 UISplitViewController 模式的变化?
好的,我找到了一个简单的解决方案。我犯了一个新手错误。诀窍是覆盖 viewWillLayoutSubviews()
而不是 viewWillAppear(animated:)
。然后一切如我所愿。似乎 viewWillLayoutSubviews()
每次包含 UISplitViewController
更改其显示模式时都会被调用(有时不止一次),而这正是我需要响应的。唯一的问题是 splitViewController
在其中一些调用中可能是 nil
,因此需要像这样实现:
override func viewWillAppear(_ animated: Bool) {
if let svc = splitViewController {
if svc.primaryHidden {
// hide the "close" UI artifact
} else {
// show the "close" UI artifact
}
}
}
作为我寻找解决方案的绊脚石的一部分,我尝试覆盖 traitCollectionDidChange(previousTraitCollection:)
。 (我尝试这个是因为我想对设备旋转做出反应。)起初我以为我在做某事,因为每当设备旋转时也会调用此函数。有趣的是(并且,令人沮丧的是)我发现调用此函数时我的视图 splitViewController
属性 是 nil
。这似乎很奇怪,因为当 UISplitViewController 重新配置自身时,viewDidDisappear(animated:)
和 viewWillAppear(animated:)
都没有被调用。但我想为什么它应该是 nil
是另一天的问题。
有 UIViewControllerShowDetailTargetDidChangeNotification
通知:
// Sometimes view controllers that are using showViewController:sender and
// showDetailViewController:sender: will need to know when the split view
// controller environment above it has changed. This notification will be
// posted when that happens (for example, when a split view controller is
// collapsing or expanding). The NSNotification's object will be the view
// controller that caused the change.
UIKIT_EXTERN NSNotificationName const UIViewControllerShowDetailTargetDidChangeNotification NS_AVAILABLE_IOS(8_0);
使用如下
- (void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showDetailTargetDidChange:) name:UIViewControllerShowDetailTargetDidChangeNotification object:self.splitViewController];
}
- (void)showDetailTargetDidChange:(NSNotification *)notification{
// changed from collapsed to expanded or vice versa
}
此 Apple 示例演示了 table 单元配件如何从纵向的披露指示器(表示将发生推送)更改为在更改为横向拆分视图时被删除: https://developer.apple.com/library/archive/samplecode/AdaptivePhotos/Introduction/Intro.html
关于 iOS 13 beta 的注意事项,将 addObserver 与对象 nil 一起使用,因为当前存在一个错误,他们使用错误的对象发送通知。他们使用来自内部 class 集群的新 UISplitViewControllerPanelImpl 而不是 UISplitViewController 对象。 http://www.openradar.appspot.com/radar?id=4956722791710720
供日后参考:
使用 UISplitViewControllerDelegate 怎么样?
它有一个名为
的方法splitViewController:willChangeToDisplayMode:
这应该完全符合您的要求。