3 回答

TA貢獻1998條經(jīng)驗 獲得超6個贊
類似于在Swift中的類擴展函數(shù)中使用'self',您可以定義一個通用的輔助方法,它從調(diào)用上下文中推斷出self的類型:
extension UIViewController{ class func instantiateFromStoryboard(storyboardName: String, storyboardId: String) -> Self { return instantiateFromStoryboardHelper(storyboardName, storyboardId: storyboardId) } private class func instantiateFromStoryboardHelper<T>(storyboardName: String, storyboardId: String) -> T { let storyboard = UIStoryboard(name: storyboardName, bundle: nil) let controller = storyboard.instantiateViewControllerWithIdentifier(storyboardId) as! T return controller }}
然后
let vc = MyViewController.instantiateFromStoryboard("name", storyboardId: "id")
編譯,類型推斷為MyViewController
。
Swift 3更新:
extension UIViewController{ class func instantiateFromStoryboard(storyboardName: String, storyboardId: String) -> Self { return instantiateFromStoryboardHelper(storyboardName: storyboardName, storyboardId: storyboardId) } private class func instantiateFromStoryboardHelper<T>(storyboardName: String, storyboardId: String) -> T { let storyboard = UIStoryboard(name: storyboardName, bundle: nil) let controller = storyboard.instantiateViewController(withIdentifier: storyboardId) as! T return controller }}
另一種可能的解決方案,使用unsafeDowncast
:
extension UIViewController{ class func instantiateFromStoryboard(storyboardName: String, storyboardId: String) -> Self { let storyboard = UIStoryboard(name: storyboardName, bundle: nil) let controller = storyboard.instantiateViewController(withIdentifier: storyboardId) return unsafeDowncast(controller, to: self) }}

TA貢獻1806條經(jīng)驗 獲得超8個贊
Self
是在編譯時確定的,而不是運行時。在你的代碼中,Self
完全等同于UIViewController
,而不是“恰好調(diào)用它的子類”。這將返回UIViewController
,調(diào)用者必須將as
它放入正確的子類中。我認為這是你想要避免的(雖然這是“正常的可可”方式,所以只返回UIViewController
可能是最好的解決方案)。
注意:initialize
在任何情況下都不應(yīng)該命名該函數(shù)。這是現(xiàn)有的類函數(shù),NSObject
并且最多會引起混淆,最壞的情況是錯誤。
但是如果你想避免調(diào)用者的話as
,子類化通常不是在Swift中添加功能的工具。相反,您通常需要泛型和協(xié)議。在這種情況下,您只需要泛型。
func instantiateViewController<VC: UIViewController>(storyboardName: String, storyboardId: String) -> VC { let storyboad = UIStoryboard(name name: storyboardName, bundle: nil) let controller = storyboad.instantiateViewControllerWithIdentifier(storyboardId) as! VC return controller}
這不是一種類方法。這只是一個功能。這里沒有必要上課。
let tvc: UITableViewController = instantiateViewController(name: name, storyboardId: storyboardId)

TA貢獻1785條經(jīng)驗 獲得超4個贊
更清潔的解決方案(至少在視覺上更整潔):
class func initialize(storyboardName: String, storyboardId: String) -> Self { // The absurdity that's Swift's type system. If something is possible to do with two functions, why not let it be just one? func loadFromImpl<T>() -> T { let storyboard = UIStoryboard(name: storyboardName, bundle: nil) return storyboard.instantiateViewController(withIdentifier: storyboardId).view as! T } return loadFromImpl()}
- 3 回答
- 0 關(guān)注
- 1531 瀏覽
添加回答
舉報