2017-02-21 79 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; 
}