奇怪的底层灰色轮廓视图试图以编程方式解除UISplitViewController的主人

时间:2016-06-21 08:23:42

标签: ios uisplitviewcontroller

我使用UISplitViewControllerpreferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay,我正在寻找一种方法来解雇主视图控制器。我的主人包含一个表视图,每当我选择一个单元格时我都想关闭它。令人惊讶的是,UISplitViewController似乎没有为此提供方法(但我确实看到Apple Mail这样做,我们在纵向模式下选择了一个电子邮件)。

我在此处发现了以下解决方法:Hiding the master view controller with UISplitViewController in iOS8(请参阅phatmann答案)。这有效,但它也会在它被解散时创建一个奇怪的动画,有一个基本的灰色轮廓视图,它不会与我的主视图一起动画。这里也报告了这个问题:iOS Swift 2 UISplitViewController opens detail screen on master's place when on iPad/ iPhone 6+

只有在我使用此解决方法解雇master时才会出现问题,而不是当我点击辅助设备时,我猜UISplitViewController在按钮上调用sendAction时不会遵循常规解除流程。

1 个答案:

答案 0 :(得分:1)

我使用以下代码来解决此问题。可能有更好的方法来匹配导致问题的特定视图。也就是说,这段代码是在Apple今年4月批准的应用程序中。代码所做的是查找特定类型的特定视图,如果找到,则会使其隐藏,直到动画完成。它有点未来的证明,因为如果它没有检测到特殊视图,它什么都不做。我还为采用者添加了一些关于您可能想要进行更改的评论。

func closePrimaryIfOpen(finalClosure fc: (() -> Void)? = nil) {
    guard let
        primaryNavController = viewControllers[0] as? MySpecialNavSubclass,
        primaryVC = primaryNavController.topViewController as? MySpecialCalss
    else { fatalError("NO Special Class?") }

    // no "official" way to know if its open or not. 
    // The view could keep track of didAppear and willDisappear, but those are not reliable
    let isOpen = primaryVC.view.frame.origin.x >= -10   // -10 because could be some slight offset when presented
    if isOpen {
        func findChromeViewInView(theView: UIView) -> UIView? {
            var foundChrome = false
            var view: UIView! = theView
            var popView: UIView!

            repeat {
                // Mirror may bring in a lot of overhead, could use NSStringFromClass
                // Also, don't match on the full class name! For sure Apple won't like that!
                //print("View: ", Mirror(reflecting: view).subjectType, " frame: \(view.frame)")
                if Mirror(reflecting: view).description.containsString("Popover") { // _UIPopoverView
                    for v in view.subviews {
                        //print("SV: ", Mirror(reflecting: v).subjectType, " frame: \(v.frame)")
                        if Mirror(reflecting: v).description.containsString("Chrome") {
                            foundChrome = true
                            popView = v
                            //popView.hidden = true
                            break
                        }
                    }
                    if foundChrome { break }
                }
                view = view.superview
            } while view != nil
            return popView
        }

        // Note: leave it as optional - Apple changes things and we don't find the view, things still work!
        let chromeView = findChromeViewInView(self.view)

        UIView.animateWithDuration(0.250, animations: {
            chromeView?.hidden = true
            self.preferredDisplayMode = .PrimaryHidden
        }, completion: { Bool in
            self.preferredDisplayMode = .PrimaryOverlay
            chromeView?.hidden = false
            if let finalClosure = fc {
                finalClosure()
            }
            //print("SLIDER CLOSED DONE!!!")
        } )
    }
}