问题
I have a ViewController instance defined in a storyboard. I can initialize it by the following
var myViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("myViewControllerIdentifier") as! ViewController
Is there a way to override the init method of ViewController so that I can initialize it using
var myViewController = ViewController()
I tried overriding init
convenience init() {
self = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
but the compiler doesn't like that. Any ideas?
回答1:
A convenience initializer must always delegate to a designated initializer for the same class, and a designated initializer must call a superclass initializer.
Since the superclass doesn't have an appropriate initializer, you would probably be better served by a class factory method:
static func instantiate() -> SearchTableViewController
{
return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
then use:
var myViewController = SearchTableViewController.instantiate()
回答2:
A class factory method is the way to go for now. Here's a protocol that you can use to quickly add makeFromStoryboard
support to all UIViewController
s.
protocol StoryboardInstantiable {
static var storyboardName: String { get }
static var storyboardBundle: NSBundle? { get }
static var storyboardIdentifier: String? { get }
}
extension StoryboardInstantiable {
static var storyboardBundle: NSBundle? { return nil }
static var storyboardIdentifier: String? { return nil }
static func makeFromStoryboard() -> Self {
let storyboard = UIStoryboard(name: storyboardName, bundle: storyboardBundle)
if let storyboardIdentifier = storyboardIdentifier {
return storyboard.instantiateViewControllerWithIdentifier(storyboardIdentifier) as! Self
} else {
return storyboard.instantiateInitialViewController() as! Self
}
}
}
Example:
extension MasterViewController: StoryboardInstantiable {
static var storyboardName: String { return "Main" }
static var storyboardIdentifier: String? { return "Master" }
}
In case the view controller is the initial view controller in the storyboard, you can simply ignore storyboardIdentifier
.
In case all the view controllers are in the same storyboard, you can also override storyboardName
under the StoryboardInstantiable
extension and return the name.
来源:https://stackoverflow.com/questions/31821883/swift-initialize-view-controller-from-storyboard-by-overriding-init