2017-02-21 77 views
0

有沒有辦法通過實例化 - 設置 - 推一個視圖控制器使用像這樣的輔助方法,但同時避免向下轉換?推送UIViewController的幫手方法

func pushController(id: String, setup: (_ vc: UIViewController) ->()) { 
    if let vc = storyboard?.instantiateViewController(withIdentifier: id) { 
    setup(vc) 
    navigationController?.pushViewController(vc, animated: true) 
    } 
} 

// usage 
pushController(id: "Cars") { vc in 
    (vc as! CarsVC).brand = "BMW" 
} 

// ...want to avoid downcasting 
vc.brand = "BMW" 
+0

周圍有鑄造沒有辦法,因爲'故事板.instantiateViewController(withIdentifier:)'總是返回類型'UIViewController',你要麼投的對象在'pushController(ID:)'方法或施放'storyboard?.i的返回值nstantiateViewController(withIdentifier:)'並且有專門的幫手。 – JAL

回答

1

我不認爲你能避免向下轉換,但是你可以把它痛苦少:

func pushController<VC: UIViewController>(id: String, setup: (_ vc: VC) ->()) { 
    if let vc = storyboard?.instantiateViewController(withIdentifier: id) as? VC { 
    setup(vc) 
    navigationController?.pushViewController(vc, animated: true) 
    } 
} 

// usage 
pushController(id: "Cars") { (vc: CarsVC) in 
    vc.brand = "BMW" 
} 

沒有測試過,所以有可能是小問題。

編輯:我應該注意,當錯誤類型與ID一起使用時,這會失敗。您可能需要在if之後添加else來處理此問題。

1

最優雅的解決方案,我能想到的是使用泛型,像這樣(操場) - 實施例:

import UIKit 

extension UIViewController { 
    func pushController<T:UIViewController> (id: String, setup: (_ vc: T) ->()) { 
     if let vc = self.storyboard?.instantiateViewController(withIdentifier: id) as? T { 
      setup(vc) 
      self.navigationController?.pushViewController(vc, animated: true) 
     } 
    } 

} 

class ViewControllerA:UIViewController {} 

class ViewControllerB:UIViewController { 
    var bValue:Int = 0 
} 

let vcA = ViewControllerA(); 

vcA.pushController(id: "B") { 
    (vc:ViewControllerB) in 
    vc.title = "view controller b" 
    vc.bValue = 42; 
} 

我寧願叫pushController有一個明確的泛型類型,但unfortunatley這種不支持斯威夫特3:

vcA.pushController<ViewControllerB>(id: "B") { // Error: cannot explicitly specialize a generic function 
    vc in 
    vc.title = "view controller b" 
    vc.bValue = 42; 
}