本文介绍了奇怪的底层灰色轮廓视图试图以编程方式解除 UISplitViewController 的主人的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use a UISplitViewController with preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay and I was looking for a way to dismiss master view controller. My master contains a table view and I'd like to close it whenever I select a cell. Surprisingly UISplitViewController doesn't seem to offer a method for that (but I do see Apple Mail doing that we you select an email in portrait mode).

我发现这里报告了以下解决方法:在 iOS8 中使用 UISplitViewController 隐藏主视图控制器(看看 phatmann 的回答).这有效,但它在被关闭时也会创建一个奇怪的动画,有一个潜在的灰色轮廓视图,它没有与我的主人的视图一起动画.这里也报告了这个问题:iOS Swift 2 UISplitViewController 在 iPad/iPhone 6+ 上打开主位置的详细信息屏幕

I found the following workaround reported here: Hiding the master view controller with UISplitViewController in iOS8 (look at phatmann answer). This works but it also creates a weird animation when it's dismissed, there's an underlying gray outlined view which is not animated together with my master's view. The problem has been reported also here: iOS Swift 2 UISplitViewController opens detail screen on master's place when on iPad/ iPhone 6+

问题仅在我使用此解决方法关闭 master 时出现,而不是在我点击辅助时出现,所以我猜 UISplitViewController 没有遵循常规的关闭流程,当您只是在按钮上调用 sendAction 时.

The problem occurs only when I dismiss master with this workaround, not when I tap on the secondary so I guess UISplitViewController is not following the regular dismiss flow when you just call sendAction on the button.

推荐答案

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

I used the following code to address this problem. There might be a better way to match on the specific view that is causing the issue. That said, this code was in an app approved by Apple in April of this year. What the code does is look for a specific view of a certain type, and if found, then it makes it hidden until the animation is complete. Its somewhat future proof, since if it does't detect the special view, it does nothing. I also added some comments for adopters on where you might want to make changes.

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!!!")
        } )
    }
}

这篇关于奇怪的底层灰色轮廓视图试图以编程方式解除 UISplitViewController 的主人的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 21:34