在iPad iOS 13上启动时,UISplitViewController将无法正确折叠 [英] UISplitViewController will not correctly collapse at launch on iPad iOS 13

查看:90
本文介绍了在iPad iOS 13上启动时,UISplitViewController将无法正确折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我的应用程序过渡到iOS 13,并且UISplitViewController折叠到详细信息视图上,而不是在启动时折叠到主视图上-仅在iPad上.另外,后退按钮也不会显示-就像它是根视图控制器一样.

我的应用程序包含一个UISplitViewController,它已被子类化,符合UISplitViewControllerDelegate.拆分视图包含两个子视图-均为UINavigationControllers,并且嵌入在UITabBarController(子类为TabViewController)

在拆分视图viewDidLoad中,将委托设置为self,将preferredDisplayMode设置为.allVisible.

由于某种原因,未调用方法splitViewController(_:collapseSecondary:onto:).

iPhone iPad 上的 iOS 12 中,在启动时正确调用了splitViewController(_:collapseSecondary:onto:)方法,介于application(didFinishLaunchingWithOptions)applicationDidBecomeActive.

iPhone 上的 iOS 13 中,在启动时在scene(willConnectTo session:)sceneWillEnterForeground之间正确调用了splitViewController(_:collapseSecondary:onto:)方法.

iPad 上的 iOS 13 中,如果窗口在启动时具有紧凑的宽度,例如在创建为拆分视图的新场景中,根本不会调用splitViewController(_:collapseSecondary:onto:)方法.仅在将窗口扩大到常规宽度然后再缩小时才调用该方法.

 class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        preferredDisplayMode = .allVisible
}

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
        print("Split view controller function")
        guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
        guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
        if topAsDetailController.passedEntry == nil {
            return true
        }
        return false
    }
}
 

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        // Setup split controller
        let tabViewController = self.window!.rootViewController as! TabViewController
        let splitViewController = tabViewController.viewControllers![0] as! SplitViewController
        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
        navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
        navigationController.topViewController!.navigationItem.leftBarButtonItem?.tintColor = UIColor(named: "Theme Colour")

        splitViewController.preferredDisplayMode = .allVisible

}

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 13.0, *) {
        } else {
            let tabViewController = self.window!.rootViewController as! TabViewController
            let splitViewController = tabViewController.viewControllers![0] as! SplitViewController
            let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
            navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
            navigationController.topViewController!.navigationItem.leftBarButtonItem?.tintColor = UIColor(named: "Theme Colour")

            splitViewController.preferredDisplayMode = .allVisible
        }

        return true
    }

我为为什么在iPhone中调用此方法而不在iPad中调用而感到困惑!我是一名新开发人员,这是我的第一篇文章,因此,如果我的代码没有提供足够的详细信息或格式不正确,则表示歉意!

解决方案

由于某些原因,特别是在iOS 13上,特别是在iPad上的traittraits中,在UISplitViewController上调用viewDidLoad之前,对委托的调用以查看是否应该折叠因此,在进行该调用时,不会设置您的委托,并且永远不会调用该方法.

如果您以编程方式创建splitViewController,这是一个简单的解决方法,但是如果您使用的是Storyboards则不是很多.您可以通过在awakeFromNib()而不是viewDidLoad()中设置委托来解决此问题.

使用原始帖子中的示例,代码示例如下

class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
    override func awakeFromNib() {
        super.awakeFromNib()
        delegate = self
        preferredDisplayMode = .allVisible
    }

    func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
        return true
    }
}

您还需要确保在crashSecondary函数中使用的任何逻辑都不会引用由于尚未调用viewDidLoad而尚未填充的变量.

I am transitioning my app to iOS 13, and the UISplitViewController collapses onto the detail view, rather than the master at launch — only on iPad. Also, the back button is not shown - as if it is the root view controller.

My app consists of a UISplitViewController which has been subclassed, conforming to UISplitViewControllerDelegate. The split view contains two children — both UINavigationControllers, and is embedded in a UITabBarController (subclassed TabViewController)

In the split view viewDidLoad, the delegate is set to self and preferredDisplayMode is set to .allVisible.

For some reason, the method splitViewController(_:collapseSecondary:onto:) not being called.

In iOS 12 on iPhone and iPad, the method splitViewController(_:collapseSecondary:onto:) is correctly called at launch, in between application(didFinishLaunchingWithOptions) and applicationDidBecomeActive.

In iOS 13 on iPhone, the method splitViewController(_:collapseSecondary:onto:) is correctly called at launch, in between scene(willConnectTo session:) and sceneWillEnterForeground.

In iOS 13 on iPad, however, if the window has compact width at launch e.g. new scene created as a split view, the splitViewController(_:collapseSecondary:onto:) method is not called at all. Only when expanding the window to regular width, and then shrinking is the method called.

class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        preferredDisplayMode = .allVisible
}

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
        print("Split view controller function")
        guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
        guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
        if topAsDetailController.passedEntry == nil {
            return true
        }
        return false
    }
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        // Setup split controller
        let tabViewController = self.window!.rootViewController as! TabViewController
        let splitViewController = tabViewController.viewControllers![0] as! SplitViewController
        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
        navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
        navigationController.topViewController!.navigationItem.leftBarButtonItem?.tintColor = UIColor(named: "Theme Colour")

        splitViewController.preferredDisplayMode = .allVisible

}

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 13.0, *) {
        } else {
            let tabViewController = self.window!.rootViewController as! TabViewController
            let splitViewController = tabViewController.viewControllers![0] as! SplitViewController
            let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
            navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
            navigationController.topViewController!.navigationItem.leftBarButtonItem?.tintColor = UIColor(named: "Theme Colour")

            splitViewController.preferredDisplayMode = .allVisible
        }

        return true
    }

It stumps me why the method is being called in iPhone, but not in iPad! I am a new developer and this is my first post, so apologies if my code doesn't give enough detail or is not correctly formatted!

解决方案

For some reason on iOS 13 specifically on the iPad in compact traitCollections the call to the delegate to see if it should collapse is happening BEFORE viewDidLoad is called on the UISplitViewController and so when it makes that call, your delegate is not set, and the method never gets called.

If you're creating your splitViewController programmatically this is an easy fix, but if you're using Storyboards not so much. You can work around this by setting your delegate in awakeFromNib() instead of viewDidLoad()

Using your example from the original post, a sample of code would be as follows

class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
    override func awakeFromNib() {
        super.awakeFromNib()
        delegate = self
        preferredDisplayMode = .allVisible
    }

    func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
        return true
    }
}

You'll also want to make sure whatever logic you're using in the collapseSecondary function isn't referencing variables that aren't yet populated since viewDidLoad hasn't been called yet.

这篇关于在iPad iOS 13上启动时,UISplitViewController将无法正确折叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆