swift - 通过覆盖 init 从故事板初始化视图控制器
swift - Initialize view controller from storyboard by overriding init
我在故事板中定义了一个 ViewController 实例。我可以通过以下方式初始化它
var myViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("myViewControllerIdentifier") as! ViewController
有没有办法覆盖 ViewController 的 init 方法,以便我可以使用
初始化它
var myViewController = ViewController()
我尝试覆盖 init
convenience init() {
self = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
但编译器不喜欢那样。有什么想法吗?
便利构造器必须始终委托给同一个 class 的指定构造器,并且指定构造器必须调用超级class 构造器。
由于 superclass 没有合适的初始化器,class 工厂方法可能会更好:
static func instantiate() -> SearchTableViewController
{
return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
然后使用:
var myViewController = SearchTableViewController.instantiate()
class 工厂方法是目前的方法。这是一个协议,您可以使用它来快速向所有 UIViewController
添加 makeFromStoryboard
支持。
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
}
}
}
示例:
extension MasterViewController: StoryboardInstantiable {
static var storyboardName: String { return "Main" }
static var storyboardIdentifier: String? { return "Master" }
}
如果视图控制器是故事板中的初始视图控制器,您可以简单地忽略storyboardIdentifier
。
如果所有视图控制器都在同一个故事板中,您还可以在 StoryboardInstantiable
扩展名和 return 名称下覆盖 storyboardName
。
你可以试试泛型。像这样:
func Tvc<T>(_ vcType: T.Type) -> T {
let vc = (vcType as! UIViewController.Type).vc//限制或明确为 UIViewController.Type
return vc as! T
}
extension UIViewController {
fileprivate static var vc: UIViewController {
let M = UIStoryboard.init(name: "V", bundle: Bundle.main)
return M.instantiateViewController(withIdentifier: "\(self)")
}
}
例子
let vc = Tvc(HLCases.self)
_vc.navigationController?.pushViewController(vc, animated: true)
我在故事板中定义了一个 ViewController 实例。我可以通过以下方式初始化它
var myViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("myViewControllerIdentifier") as! ViewController
有没有办法覆盖 ViewController 的 init 方法,以便我可以使用
初始化它var myViewController = ViewController()
我尝试覆盖 init
convenience init() {
self = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
但编译器不喜欢那样。有什么想法吗?
便利构造器必须始终委托给同一个 class 的指定构造器,并且指定构造器必须调用超级class 构造器。
由于 superclass 没有合适的初始化器,class 工厂方法可能会更好:
static func instantiate() -> SearchTableViewController
{
return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}
然后使用:
var myViewController = SearchTableViewController.instantiate()
class 工厂方法是目前的方法。这是一个协议,您可以使用它来快速向所有 UIViewController
添加 makeFromStoryboard
支持。
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
}
}
}
示例:
extension MasterViewController: StoryboardInstantiable {
static var storyboardName: String { return "Main" }
static var storyboardIdentifier: String? { return "Master" }
}
如果视图控制器是故事板中的初始视图控制器,您可以简单地忽略storyboardIdentifier
。
如果所有视图控制器都在同一个故事板中,您还可以在 StoryboardInstantiable
扩展名和 return 名称下覆盖 storyboardName
。
你可以试试泛型。像这样:
func Tvc<T>(_ vcType: T.Type) -> T {
let vc = (vcType as! UIViewController.Type).vc//限制或明确为 UIViewController.Type
return vc as! T
}
extension UIViewController {
fileprivate static var vc: UIViewController {
let M = UIStoryboard.init(name: "V", bundle: Bundle.main)
return M.instantiateViewController(withIdentifier: "\(self)")
}
}
例子
let vc = Tvc(HLCases.self)
_vc.navigationController?.pushViewController(vc, animated: true)