iOS Swift:容器视图内嵌入SplitViewController的实现问题
Hey there! I get it—you tweaked the tutorial's structure by adding a new initial ViewController with a container view embedding the SplitViewController, and now the AppDelegate code from the tutorial is breaking. Let's figure out why and fix this step by step.
Why the Original Code Isn't Working
The tutorial’s original code assumes the window’s rootViewController is directly the SplitViewController. But in your setup, the root is your custom initial ViewController, so when you run guard let splitViewController = window?.rootViewController as? UISplitViewController, it fails because the root isn’t a SplitViewController anymore.
Solution: Access the SplitViewController from Your Initial VC
You need to first reference your custom initial ViewController, then grab the embedded SplitViewController from it. Here’s how to do it properly:
Step 1: Track the Embedded SplitViewController in Your Initial VC
First, update your initial ViewController class to keep a reference to the SplitViewController that’s embedded via the container view segue. Make sure you set an identifier for your embed segue in Interface Builder first (e.g., "EmbedSplitSegue").
class InitialViewController: UIViewController { // Store a reference to the embedded SplitViewController var embeddedSplitVC: UISplitViewController? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { super.prepare(for: segue, sender: sender) // Check if this is the embed segue for the SplitViewController if segue.identifier == "EmbedSplitSegue" { embeddedSplitVC = segue.destination as? UISplitViewController } } }
Alternatively, if you don’t want to use a segue identifier, you can find the SplitViewController in viewDidLoad:
override func viewDidLoad() { super.viewDidLoad() // Look for the SplitViewController among child view controllers embeddedSplitVC = childViewControllers.first(where: { $0 is UISplitViewController }) as? UISplitViewController }
Step 2: Update the AppDelegate Code
Now, modify the application(_:didFinishLaunchingWithOptions:) method in AppDelegate to first get your initial ViewController, then pull the SplitViewController from it:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 1. Get the initial root ViewController guard let initialVC = window?.rootViewController as? InitialViewController else { print("Could not access the initial ViewController") return true } // 2. Get the embedded SplitViewController from the initial VC guard let splitViewController = initialVC.embeddedSplitVC else { print("Could not access the embedded SplitViewController") return true } // 3. Now run the tutorial's original code here (example below) if let navigationController = splitViewController.viewControllers.last as? UINavigationController { navigationController.topViewController?.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem splitViewController.delegate = self // Don't forget to conform to UISplitViewControllerDelegate if needed } return true }
Key Notes
- Double-check that your embed segue has the correct identifier if you use the segue-based approach.
- If you’re using storyboards, ensure your custom initial ViewController is set as the Initial View Controller in the storyboard settings.
- Make sure your AppDelegate conforms to
UISplitViewControllerDelegateif the tutorial requires it (addextension AppDelegate: UISplitViewControllerDelegate { ... }if needed).
This should get your setup working just like the tutorial, while keeping your custom initial ViewController structure intact.
内容的提问来源于stack exchange,提问作者Tom

