UIViewController 生命周期断了 iOS13,makeKeyAndVisible() 好像不能操作?

Sté*_*uca 6 uiviewcontroller uistoryboardsegue swift5 ios13

我有一个自定义的 UIStoryboardSegue,可以在 iOS12.* 中按需要工作。

目标视图控制器之一是 UITabbarController:对于每个选项卡,我都有一个嵌入在导航控制器中的控制器。

不幸的是,对于 iOS13.*,这不能很好地工作:视图控制器生命周期被破坏,并且不再调用 viewXXXAppear() 和 willTransition() 方法。

看起来 makeKeyAndVisible() 没有效果?!

在底部查看屏幕 UI 在没有调用 viewWillAppear() 的情况下是如何困惑的。

一个可怕的临时解决方法

我不得不拉我的头发,但是,我找到了一个公开的修复程序(我必须即时添加导航控制器)。

这弄乱了 vc 层次结构:你有更好的解决方案吗?

public class AladdinReplaceRootViewControllerSegue: UIStoryboardSegue {
    override public func perform() {

        guard let window = UIApplication.shared.delegate?.window as? UIWindow,
            let sourceView = source.view,
            let destinationView = destination.view else {
            super.perform()
            return
        }

        let screenWidth  = UIScreen.main.bounds.size.width
        let screenHeight = UIScreen.main.bounds.size.height

        destinationView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)

        window.insertSubview(destinationView, aboveSubview: sourceView)


        // **My fix**
        if #available(iOS 13,*) {
            // I introduced an invisible navigation controller starting in iOS13 otherwise, my controller attached to the tabbar thru a navigation, dont work correctly, no viewXAppearis called.
            let navigationController = UINavigationController.init(rootViewController: self.destination)
            navigationController.isNavigationBarHidden = true
            window.rootViewController = navigationController
        }
        else {
            window.rootViewController = self.destination
        }

        window.makeKeyAndVisible()
    }
}
Run Code Online (Sandbox Code Playgroud)

用户界面被破坏

mes*_*esh 1

我找到了一个解决方案,感谢使用自定义转场对开始/结束外观转换进行不平衡调用 这里发生的是目标视图控制器的创建和附加发生了两次,并且第一次发生得太快了。所以你需要做的是:

public class AladdinReplaceRootViewControllerSegue: UIStoryboardSegue {
    override public func perform() {

        guard let window = UIApplication.shared.delegate?.window as? UIWindow,
            let sourceView = source.view,
            let destinationView = destination.view else {
            super.perform()
            return
        }

        let screenWidth  = UIScreen.main.bounds.size.width
        let screenHeight = UIScreen.main.bounds.size.height

        let mock = createMockView(view: desination.view)
        window.insertSubview(mock, aboveSubview: sourceView)

        //DO SOME ANIMATION HERE< MIGHT NEED TO DO mock.alpha = 0

        //after the animation is done:
        window.rootViewController = self.destination
        mock.removeFromSuperview()
    }

    func createMockView(view: UIView) -> UIImageView {
        UIGraphicsBeginImageContextWithOptions(view.frame.size, true, UIScreen.main.scale)

        view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()
        return UIImageView(image: image)    
    }   
}
Run Code Online (Sandbox Code Playgroud)