在Swift中返回instancetype

在Swift中返回instancetype

我正在尝试进行此扩展:

extension UIViewController{
    class func initialize(storyboardName: String, storyboardId: String) -> Self
    {
        let storyboad = UIStoryboard(name: storyboardName, bundle: nil)
        let controller = storyboad.instantiateViewControllerWithIdentifier(storyboardId) as! Self

        return controller    }}

但我得到编译错误:

错误:无法将'UIViewController'类型的返回表达式转换为返回类型'Self'

可能吗?我也想成为init(storyboardName: String, storyboardId: String)


慕田峪9158850
浏览 1398回答 3
3回答

米琪卡哇伊

类似于在Swift中的类扩展函数中使用'self',您可以定义一个通用的辅助方法,它从调用上下文中推断出self的类型:extension&nbsp;UIViewController{ &nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;func&nbsp;instantiateFromStoryboard(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;Self &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;instantiateFromStoryboardHelper(storyboardName,&nbsp;storyboardId:&nbsp;storyboardId) &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;class&nbsp;func&nbsp;instantiateFromStoryboardHelper<T>(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;storyboard&nbsp;=&nbsp;UIStoryboard(name:&nbsp;storyboardName,&nbsp;bundle:&nbsp;nil) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;controller&nbsp;=&nbsp;storyboard.instantiateViewControllerWithIdentifier(storyboardId)&nbsp;as!&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;controller&nbsp;&nbsp;&nbsp;&nbsp;}}然后let&nbsp;vc&nbsp;=&nbsp;MyViewController.instantiateFromStoryboard("name",&nbsp;storyboardId:&nbsp;"id")编译,类型推断为MyViewController。Swift 3更新:extension&nbsp;UIViewController{ &nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;func&nbsp;instantiateFromStoryboard(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;Self &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;instantiateFromStoryboardHelper(storyboardName:&nbsp;storyboardName,&nbsp;storyboardId:&nbsp;storyboardId) &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;class&nbsp;func&nbsp;instantiateFromStoryboardHelper<T>(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;storyboard&nbsp;=&nbsp;UIStoryboard(name:&nbsp;storyboardName,&nbsp;bundle:&nbsp;nil) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;controller&nbsp;=&nbsp;storyboard.instantiateViewController(withIdentifier:&nbsp;storyboardId)&nbsp;as!&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;controller&nbsp;&nbsp;&nbsp;&nbsp;}}另一种可能的解决方案,使用unsafeDowncast:extension&nbsp;UIViewController{ &nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;func&nbsp;instantiateFromStoryboard(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;Self &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;storyboard&nbsp;=&nbsp;UIStoryboard(name:&nbsp;storyboardName,&nbsp;bundle:&nbsp;nil) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;controller&nbsp;=&nbsp;storyboard.instantiateViewController(withIdentifier:&nbsp;storyboardId) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;unsafeDowncast(controller,&nbsp;to:&nbsp;self) &nbsp;&nbsp;&nbsp;&nbsp;}}

慕森卡

Self是在编译时确定的,而不是运行时。在你的代码中,Self完全等同于UIViewController,而不是“恰好调用它的子类”。这将返回UIViewController,调用者必须将as它放入正确的子类中。我认为这是你想要避免的(虽然这是“正常的可可”方式,所以只返回UIViewController可能是最好的解决方案)。注意:initialize在任何情况下都不应该命名该函数。这是现有的类函数,NSObject并且最多会引起混淆,最坏的情况是错误。但是如果你想避免调用者的话as,子类化通常不是在Swift中添加功能的工具。相反,您通常需要泛型和协议。在这种情况下,您只需要泛型。func&nbsp;instantiateViewController<VC:&nbsp;UIViewController>(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;VC&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;storyboad&nbsp;=&nbsp;UIStoryboard(name&nbsp;name:&nbsp;storyboardName,&nbsp;bundle:&nbsp;nil) &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;controller&nbsp;=&nbsp;storyboad.instantiateViewControllerWithIdentifier(storyboardId)&nbsp;as!&nbsp;VC&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;controller}这不是一种类方法。这只是一个功能。这里没有必要上课。let&nbsp;tvc:&nbsp;UITableViewController&nbsp;=&nbsp;instantiateViewController(name:&nbsp;name,&nbsp;storyboardId:&nbsp;storyboardId)

九州编程

更清洁的解决方案(至少在视觉上更整洁):class&nbsp;func&nbsp;initialize(storyboardName:&nbsp;String,&nbsp;storyboardId:&nbsp;String)&nbsp;->&nbsp;Self&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;absurdity&nbsp;that's&nbsp;Swift's&nbsp;type&nbsp;system.&nbsp;If&nbsp;something&nbsp;is&nbsp;possible&nbsp;to&nbsp;do&nbsp;with&nbsp;two&nbsp;functions,&nbsp;why&nbsp;not&nbsp;let&nbsp;it&nbsp;be&nbsp;just&nbsp;one?&nbsp;&nbsp;&nbsp;&nbsp;func&nbsp;loadFromImpl<T>()&nbsp;->&nbsp;T&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;storyboard&nbsp;=&nbsp;UIStoryboard(name:&nbsp;storyboardName,&nbsp;bundle:&nbsp;nil) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;storyboard.instantiateViewController(withIdentifier:&nbsp;storyboardId).view&nbsp;as!&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;loadFromImpl()}
打开App,查看更多内容
随时随地看视频慕课网APP