Swift iOS中如何在instantiateViewController中动态指定类型转换的类
Dynamic View Controller Instantiation in Swift (No Hardcoded Class Names)
Hey there! Let's solve this problem where you want to avoid hardcoding view controller class names when using instantiateViewController(withIdentifier:). Here are a couple of practical, clean approaches to achieve dynamic type casting:
1. Use a Generic Function (Recommended)
This is the most flexible approach—you can specify the target view controller type directly when calling the function, no hardcoding needed.
Implementation:
import UIKit func instantiateViewController<T: UIViewController>(from storyboard: UIStoryboard, withIdentifier identifier: String) -> T? { // Instantiate and cast to the generic type T (a UIViewController subclass) return storyboard.instantiateViewController(withIdentifier: identifier) as? T } // Optional: A throwing version for safer error handling func instantiateViewControllerOrThrow<T: UIViewController>(from storyboard: UIStoryboard, withIdentifier identifier: String) throws -> T { guard let viewController = storyboard.instantiateViewController(withIdentifier: identifier) as? T else { throw NSError( domain: "ViewControllerInstantiationError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to cast instantiated VC to type \(T.self)"] ) } return viewController }
How to Use:
// For ExampleViewController if let exampleVC = instantiateViewController(from: mainStoryBoard, withIdentifier: self.screenPresenter.screenPresenterIdentifier) as ExampleViewController { // Use exampleVC present(exampleVC, animated: true) } // For another view controller (e.g., SettingsViewController) do { let settingsVC = try instantiateViewControllerOrThrow(from: mainStoryBoard, withIdentifier: "SettingsVC") as SettingsViewController navigationController?.pushViewController(settingsVC, animated: true) } catch { print("Error: \(error.localizedDescription)") }
2. Dynamic Cast Using an Existing Object's Type
If you already have an instance of the target view controller (like your object_name = ExampleViewController()), you can use type(of:) to get its type dynamically:
Implementation & Usage:
// Your existing object let referenceObject = ExampleViewController() // Get the type of the reference object let targetType = type(of: referenceObject) // Instantiate and cast dynamically if let screen = mainStoryBoard.instantiateViewController(withIdentifier: self.screenPresenter.screenPresenterIdentifier) as? targetType { // screen is now of type ExampleViewController present(screen, animated: true) }
Bonus: Wrap This in a Function
To make this reusable, you can wrap it in a function that takes the reference object:
func instantiateMatchingViewController<T: UIViewController>(for referenceObject: T, from storyboard: UIStoryboard, identifier: String) -> T? { return storyboard.instantiateViewController(withIdentifier: identifier) as? T } // Usage let exampleRef = ExampleViewController() if let screen = instantiateMatchingViewController(for: exampleRef, from: mainStoryBoard, identifier: self.screenPresenter.screenPresenterIdentifier) { // Use screen }
Key Notes
- Always ensure the storyboard identifier matches exactly what's set in your Storyboard file—mismatched identifiers will cause instantiation to fail.
- The generic approach is preferred because it avoids creating unnecessary view controller instances (you don't need a
referenceObjectjust to get the type). - Using the throwing function adds safety by making failure explicit, instead of silently returning
nil.
内容的提问来源于stack exchange,提问作者Shreyas sethi
相关产品推荐
相关产品推荐

