【问题标题】:Detect when UISplitViewController changes display mode检测 UISplitViewController 何时更改显示模式
【发布时间】:2018-10-15 10:33:30
【问题描述】:

我正在尝试使用 UISplitViewController,其中辅助控制器应在 UISplitViewController 处于并排模式时公开“关闭”功能(通过按钮或按钮栏项),但应在其他位置隐藏该功能次。我试着把它放在辅助视图控制器中:

override func viewWillAppear(_ animated: Bool) {
    if splitViewController!.primaryHidden {
        // hide the "close" UI artifact
    } else {
        // show the "close" UI artifact
    }
}

这会在第一次显示辅助视图时正确设置“关闭”函数的可见性,但如果 UISplitViewController 在展开和折叠之间切换(例如,通过旋转 iPhone 6s Plus),则不会再次调用此函数(这是有道理的,因为辅助控制器仍然可见)。因此,即使 UISplitViewController 更改模式,“关闭”功能仍保持其初始状态(隐藏或显示)。

如何让“关闭”功能隐藏或显示以响应 UISplitViewController 模式的变化?

【问题讨论】:

  • 你能上传一些问题的照片吗?我在我的应用程序中使用了 4 个 SplitViewController,它们让我头疼。如果可以的话,我会尽力提供帮助,但通过一些问题的图片以及您希望它的外观让我更容易理解

标签: ios uisplitviewcontroller


【解决方案1】:

供将来参考:

如何使用 UISplitViewControllerDelegate??

它有一个方法叫

splitViewController:willChangeToDisplayMode:

这应该完全符合您的要求。

Documentation here

【讨论】:

    【解决方案2】:

    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 示例演示了表格单元格附件如何从纵向显示指示符(表示将发生推送)变为在更改为横向拆分视图时将其移除: https://developer.apple.com/library/archive/samplecode/AdaptivePhotos/Introduction/Intro.html

    注意在 iOS 13 beta 上,使用带有对象 nil 的 addObserver,因为目前存在一个错误,他们使用错误的对象发送通知。他们使用来自内部类集群的新 UISplitViewControllerPanelImpl 而不是 UISplitViewController 对象。 http://www.openradar.appspot.com/radar?id=4956722791710720

    【讨论】:

    • UIViewControllerShowDetailTargetDidChangeNotification 永远不会被调用。任何想法为什么?
    • 如果在 iOS13 beta 上,将 addObserver 更改为使用 object nil。他们目前使用错误的对象来过滤通知,但我已提交反馈以解决该问题。
    • 感谢@malhal 的回复。我在 iOS 12.4 中也看到了这个问题。我尝试同时传递 nil 和 splitvc NotificationCenter.default.addObserver(self, selector: #selector(handleSplitVCTransition), name: UIViewController.showDetailTargetDidChangeNotification, object: nil)。但两人都没有被解雇
    • 请尝试我刚刚添加到答案中的Apple示例,并检查是否出现通知。我喜欢使用 iPhone 8 Plus 模拟器进行测试。
    • 谢谢。我会试试看
    【解决方案3】:

    好的,我找到了一个简单的解决方案。我犯了一个新手错误。诀窍是覆盖viewWillLayoutSubviews() 而不是viewWillAppear(animated:)。然后一切都按我的意愿进行。似乎每次包含UISplitViewController 更改其显示模式时都会调用viewWillLayoutSubviews()(有时不止一次),而这正是我需要响应的。唯一的问题是 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,我想,这是另一个问题。

    【讨论】:

      猜你喜欢
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 2013-05-08
      • 1970-01-01
      相关资源
      最近更新 更多