UIViewController扩展从storyboard实例化 [英] UIViewController extension to instantiate from storyboard
问题描述
我正在尝试在Swift中编写一个小扩展来处理故事板中 UIViewController
的实例化。
我的想法如下:自 UIStoryboard
的方法 instantiateViewControllerWithIdentifier
需要一个标识符来实例化给定的故事板的视图控制器,为什么不在我的故事板中为每个视图控制器分配一个等于其确切类名的标识符(即 UserDetailViewController
将具有UserDetailViewController的标识符,并在UIViewController上创建一个类方法:
- 接受
UIStoryboard
实例作为唯一参数 - 将当前类名称作为字符串
- 调用
instantiateViewControllerWithIdentifier
,类名作为参数 - 获取新创建的
UIViewController
实例,并返回它
所以,而不是(将类名重复为字符串,不是很好)
let vc = self.story board?.instantiateViewControllerWithIdentifier(UserDetailViewController)as UserDetailViewController
它将是:
let vc = UserDetailViewController.instantiateFromStoryboard(self.storyboard!)
我过去常常在Objective-C中使用以下类别:
+(instancetype )instantiateFromStoryboard:(UIStoryboard *)storyboard
{
return [storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([self class])];
}
但我完全坚持使用Swift版本。我希望有某种方法可以做到这一点。
我尝试了以下内容:
扩展名UIViewController {
class func instantiateFromStoryboard(storyboard:UIStoryboard) - > ; Self {
return storyboard.instantiateViewControllerWithIdentifier(NSStringFromClass(Self))
}
}
返回自我
而不是 AnyObject
允许类型推断工作。否则,我必须抛出这个方法的每一个返回,这很烦人,但也许你有一个更好的解决方案?
这给了我错误:使用未解析的标识符'Self'
NSStringFromClass
部分似乎是问题所在。
您怎么看?
-
有没有办法从类函数返回
Self
? / p> -
如果不需要每次都抛出返回值,你将如何工作? (即保持
- >自我
作为返回值)
谢谢。
如何将扩展名写入 UIStoryboard
而不是 UIViewController
?
extension UIStoryboard {
func instantiateVC< T :UIViewController>() - > T' {
//获取Swift
中类的类名和demangle如果让name = NSStringFromClass(T.self)?. componentsSeparatedByString(。)。last {
return instantiateViewControllerWithIdentifier(name )作为? T
}
返回nil
}
}
即使采用这种方法,使用方的成本也很低。
让vc:UserDetailViewController? = aStoryboard.instantiateVC()
I'm trying to write a little extension in Swift to handle instantiation of a UIViewController
from a storyboard.
My idea is the following: Since UIStoryboard
's method instantiateViewControllerWithIdentifier
needs an identifier to instantiate a given storyboard's view controller, why don't assign every view controller in my storyboard an identifier equal to its exact class name (i.e a UserDetailViewController
would have an identifier of "UserDetailViewController"), and, create a class method on UIViewController that would:
- accept a
UIStoryboard
instance as a unique parameter - get the current class name as a string
- call
instantiateViewControllerWithIdentifier
on the storyboard instance with the class name as a parameter - get the newly created
UIViewController
instance, and return it
So, instead of (which repeats the class name as a string, not very nice)
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("UserDetailViewController") as UserDetailViewController
it would be:
let vc = UserDetailViewController.instantiateFromStoryboard(self.storyboard!)
I used to do it in Objective-C with the following category:
+ (instancetype)instantiateFromStoryboard:(UIStoryboard *)storyboard
{
return [storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([self class])];
}
But I'm completely stuck with the Swift version. I hope is that there is some kind of way to do it. I tried the following:
extension UIViewController {
class func instantiateFromStoryboard(storyboard: UIStoryboard) -> Self {
return storyboard.instantiateViewControllerWithIdentifier(NSStringFromClass(Self))
}
}
Returning Self
instead of AnyObject
allows the type inference to work. Otherwise, I would have to cast every single return of this method, which is annoying, but maybe you have a better solution?
This gives me the error: Use of unresolved identifier 'Self'
The NSStringFromClass
part seems to be the problem.
What do you think?
Is there any way to return
Self
from class functions?How would you get this working without the need to cast the return value every time? (i.e keeping
-> Self
as return value)
Thanks.
How about writing an extension to UIStoryboard
instead of 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
}
}
Even adopting this approach, cost of an use side is low as well.
let vc: UserDetailViewController? = aStoryboard.instantiateVC()
这篇关于UIViewController扩展从storyboard实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!