我正在尝试用 Swift 编写一个小扩展来处理 Storyboard中 UIViewController
的实例化。
我的想法如下:既然 UIStoryboard
的方法 instantiateViewControllerWithIdentifier
需要一个标识符来实例化给定 Storyboard的 View Controller ,为什么不分配我的每个 View Controller Storyboard一个等于其确切类名的标识符(即 UserDetailViewController
将具有“UserDetailViewController”的标识符),并在 UIViewController 上创建一个类方法:
- 接受一个
UIStoryboard
实例作为唯一参数 - 以字符串形式获取当前类名
- 以类名作为参数在 Storyboard实例上调用
instantiateViewControllerWithIdentifier
- 获取新创建的
UIViewController
实例,并返回
所以,而不是(将类名作为字符串重复,不是很好)
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("UserDetailViewController") as UserDetailViewController
它会是:
let vc = UserDetailViewController.instantiateFromStoryboard(self.storyboard!)
我曾经在 Objective-C 中使用以下类别进行操作:
+ (instancetype)instantiateFromStoryboard:(UIStoryboard *)storyboard
{
return [storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([self class])];
}
但我完全坚持使用 Swift 版本。我希望有某种方法可以做到这一点。 我尝试了以下方法:
extension UIViewController {
class func instantiateFromStoryboard(storyboard: UIStoryboard) -> Self {
return storyboard.instantiateViewControllerWithIdentifier(NSStringFromClass(Self))
}
}
返回 Self
而不是 AnyObject
允许类型推断工作。否则,我将不得不转换此方法的每个返回值,这很烦人,但也许您有更好的解决方案?
这给了我错误:Use of unresolved identifier 'Self'
NSStringFromClass
部分似乎是问题所在。
你怎么看?
有没有办法从类函数中返回
Self
?如果不需要每次都强制转换返回值,您将如何使它工作? (即保持
-> Self
作为返回值)
最佳答案
如何编写 UIStoryboard
的扩展而不是 UIViewController
?
extension UIStoryboard {
func instantiateVC<T: UIViewController>() -> T? {
// get a class name and demangle for classes in Swift
if let name = NSStringFromClass(T.self)?.componentsSeparatedByString(".").last {
return instantiateViewControllerWithIdentifier(name) as? T
}
return nil
}
}
即使采用这种方式,使用端的成本也很低。
let vc: UserDetailViewController? = aStoryboard.instantiateVC()
关于ios - 从 Storyboard实例化的 UIViewController 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26056062/