UISplitViewController在ipadios13上发布时不会正确折叠

UISplitViewController在ipadios13上发布时不会正确折叠,ios,swift,ipad,uisplitviewcontroller,ios13,Ios,Swift,Ipad,Uisplitviewcontroller,Ios13,我正在将我的应用程序转换到iOS 13,UISplitViewController将折叠到细节视图,而不是发布时的主视图-仅在iPad上。此外,不会显示“后退”按钮,就像它是根视图控制器一样 我的应用程序由一个UISplitViewController组成,它已被子类化,符合UISplitViewControllerDelegate。拆分视图包含两个子视图-都是UINavigationControllers,并嵌入到UITabBarController(子类为TabViewController)

我正在将我的应用程序转换到iOS 13,UISplitViewController将折叠到细节视图,而不是发布时的主视图-仅在iPad上。此外,不会显示“后退”按钮,就像它是根视图控制器一样

我的应用程序由一个
UISplitViewController
组成,它已被子类化,符合
UISplitViewControllerDelegate
。拆分视图包含两个子视图-都是
UINavigationControllers
,并嵌入到
UITabBarController
(子类为
TabViewController

在拆分视图
viewDidLoad
中,代理设置为
self
preferredDisplayMode
设置为
.allVisible

由于某些原因,没有调用方法
splitViewController(u:collapseSecondary:on:)

在iPhone和iPad上的iOS 12中,在启动时正确调用方法
splitViewController(\uuuOpseClapseSecondary:on:)
,介于
应用程序(使用选项完成启动)
ApplicationIDBecomeActive
之间

在iPhone上的iOS 13中,在启动时正确调用了方法
splitViewController(uu2;:collapseSecondary:on:)
,在
场景(将连接到会话:)
场景界面前景之间

但是,在iPad上的iOS 13中,如果窗口在启动时具有紧凑的宽度,例如作为分割视图创建的新场景,则根本不会调用分割视图控制器(uu:collapseSecondary:on:)
方法。仅当将窗口扩展到规则宽度,然后收缩时,才调用该方法

class SplitViewController:UISplitViewController、UISplitViewController和UISplitViewController Delegate{
重写func viewDidLoad(){
super.viewDidLoad()
self.delegate=self
preferredDisplayMode=.allVisible
}
func splitViewController(uSplitViewController:UISplitViewController,将第二个辅助ViewController:UIViewController折叠到主ViewController:UIViewController)->Bool{
打印(“分割视图控制器功能”)
guard let secondaryAsNavController=secondaryViewController作为?UINavigationController else{return false}
guard让topAsDetailController=secondaryAsNavController.topViewController为?DetailViewController else{return false}
如果topAsDetailController.passedEntry==nil{
返回真值
}
返回错误
}
}

这让我很困惑,为什么在iPhone中调用这个方法,而不是在iPad中!我是一名新开发人员,这是我的第一篇帖子,如果我的代码没有提供足够的细节或格式不正确,我深表歉意

您需要在类“SceneDelegate”中的函数“scene”中添加此项:

splitViewController.delegate=self

例如:

    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

    splitViewController.delegate = self//<<<<<<<<add this

    }
class SceneDelegate:UIResponder,UIWindowSceneDelegate{
func场景(场景:UIScene,willConnectTo会话:UISceneSession,选项connectionOptions:UIScene.connectionOptions){
//设置分割控制器
让tabViewController=self.window!.rootViewController为!tabViewController
设splitViewController=tabViewController.ViewController![0]为!splitViewController
将navigationController=splitViewController.ViewController[splitViewController.ViewController.count-1]设为!UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem=splitViewController.displayModeButtonItem
navigationController.topViewController!.navigationItem.leftBarButtonItem?.tintColor=UIColor(名为:“主题颜色”)
splitViewController.preferredDisplayMode=.allVisible

splitViewController.delegate=self//由于某些原因,在iOS 13上,特别是在iPad上的compact traitCollections中,在UISplitViewController上调用viewDidLoad之前,会调用委托以查看它是否应该崩溃,因此当它调用时,不会设置委托,并且永远不会调用该方法

如果您以编程方式创建splitViewController,这是一个简单的解决方案,但如果您使用的故事板并不多。您可以通过在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
    }
}

您还需要确保collapseSecondary函数中使用的任何逻辑都不会引用尚未填充的变量,因为viewDidLoad尚未被调用。

我有一个Xcode项目,现在用于iOS 13,它使用一个选项卡栏控制器,该控制器与五个拆分视图控制器有关系,每个控制器都有自己的主视图详图(表格)视图和控制器

以前-iOS 12.x和更早版本,事实上早在我编写Objective-C时-我的分割视图控制器委托是在每个(父)主视图控制器的代码中设置的拆分视图控制器-我在子类
UITableViewController
viewDidLoad
方法中设置委托。这在iPhone和iPad上都成功运行了多年

e、 g

要明确的是,我没有子类化选项卡栏控制器或拆分视图控制器

随着Xcode 11和iOS 13的发布,主视图控制器中的拆分视图控制器委托方法不再被调用

需要明确的是,对于iOS 13,无论是设备还是模拟器,
splitViewController(\uu:collapseSecondary:on:)
都不会被调用(使用断点进行测试),其结果是:

  • iPhone-当应用程序在设备或模拟器上运行时,显示详细视图控制器
  • iPad——当应用程序在设备或模拟器上运行时,细节视图控制器就会出现,没有后退按钮,因此没有明显的机制来“逃离”细节视图
        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
    
        splitViewController.delegate = self//<<<<<<<<add this
    
        }
    
    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
        }
    }
    
    class MasterViewController: UITableViewController, UISplitViewControllerDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            splitViewController?.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
            splitViewController?.delegate = self
            ...
        }
    
        func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
            ...
        }
    }
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDelegate {
    
        var window: UIWindow?
    
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
            guard let window = window else { return }
            guard let tabBarController = window.rootViewController as? UITabBarController else { return }
    
            guard let splitViewController = tabBarController.viewControllers?.first as? UISplitViewController else { return }
    
            splitViewController.delegate = self
            splitViewController.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
        }
    
        ...
    
        func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
            ...
        }
    
    }
    
        guard let window = window else { return }
        guard let tabBarController = window.rootViewController as? UITabBarController else { return }
    
        guard let splitViewControllers = tabBarController.viewControllers else { return }
    
        for controller in splitViewControllers {
    
            guard let splitViewController = controller as? UISplitViewController else { return }
            splitViewController.delegate = self
            splitViewController.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
        }
    
        guard let window = window else { return }
        guard let tabBarController = window.rootViewController as? UITabBarController else { return }
    
        guard let splitViewControllers = tabBarController.viewControllers else { return }
    
        for controller in splitViewControllers {
    
            guard let splitViewController = controller as? UISplitViewController else { return }
            guard let navigationController = splitViewController.viewControllers.first else { return }
            guard let masterViewController = navigationController.children.first else { return }
            splitViewController.delegate = masterViewController as? UISplitViewControllerDelegate
            splitViewController.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
        }
    
    class MasterViewController: UITableViewController, UISplitViewControllerDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // the following two calls now in the scene(_:willConnectTo:options:) method...
            // splitViewController?.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
            // splitViewController?.delegate = self
            ...
        }
    
        func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
            ...
        }
    }
    
    func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
            ...
    }
    
      @available(iOS 14.0, *)
      func splitViewController(_ svc: UISplitViewController, topColumnForCollapsingToProposedTopColumn proposedTopColumn: UISplitViewController.Column) -> UISplitViewController.Column {
            return .primary
      }