2017-02-21 181 views
1

在以下代码中,基于字符串比较,我决定将显示哪个VC。避免在swift中重复代码

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    dataObj = frc.object(at: indexPath) as! Data_Object 
    var pvc: UIViewController? 

    if dataObj.type == "X" { 

     let obj = MainStoryboard().instantiateViewController(withIdentifier: "XVC") as! XVC 
     obj.data = dataObj 
     obj.isFull = true 
     obj.delegate = self 
     pvc = obj as UIViewController 

    } else if dataObj.type == "Y" { 

     let obj = MainStoryboard().instantiateViewController(withIdentifier: "YVC") as! YVC 
     obj.data = dataObj 
     obj.isFull = true 
     obj.delegate = self 
     pvc = obj as UIViewController 

    } else { 

     let obj = MainStoryboard().instantiateViewController(withIdentifier: "ZVC") as! ZVC 
     obj.data = dataObj 
     obj.isFull = true 
     obj.delegate = self 
     pvc = obj as UIViewController 
    } 

    obj.modalPresentationStyle = .popover 
    let popPVC = pvc?.popoverPresentationController 
    popPVC?.sourceView = self.view 
    self.present(pvc!, animated: true, completion: nil) 
} 

现在,除了类名,所有的代码都是重复的,我想避免这种情况。但是,迅速没有NSClassFromString

我该如何做到这一点?我应该使用泛型/模板吗?有什么建议么!

对不起,如果我在这里失去了一些愚蠢的东西。

+1

是的,你可以创建简单的功能实现这个字符串(说明:SomeViewController.self) –

回答

3

去除的重复数据删除是显而易见的:

let identifier: String 

switch dataObj.type { 
    case "X": 
     identifier = "XVC" 
    case "Y": 
     identifier = "YVC" 
    default: 
     identifier = "ZVC" 
} 

let pvc = MainStoryboard().instantiateViewController(withIdentifier: identifier) as! PVC 
pvc.data = dataObj 
pvc.isFull = true 
pvc.delegate = self 

哪里PVC为您3个控制器,例如公共超:

class PVC : UIViewController {} 
class XVC : PVC {} 
class YVC : PVC {} 
class ZVC : PVC {} 

如果你的3类不具有共同的父类,你可以使用一个协议而不是:

protocol PVC : class { 
    var data: ... 
    var isFul: ... 
    weak var delegate: ... 
} 

,并通过你的3类实现它:

总之,删除重复项,您需要为3个控制器添加一个通用接口。使用一个通用的超类或协议。

+0

非常感谢您的时间。这对我帮助很大。 :) –

0

您可以创建一个获取标识符并返回viewcontroller的函数。由于您的XVC,YVC,ZVC确实有相似性,也可以让他们的子类其他VC的有比如data, isFull,...

而且他们的财产,你可以使用类似于NSClassFromStringString(describing: SomeViewController.self)将返回SomeViewController

2

编辑

我喜欢Sulthan的答案,因为它是清洁,地雷(不得不承认...)

要完成我的,getControllerFor:type需要返回一个父类。忘了提它

我编辑的第一回答正确一些失误,并使其更简洁

先回答

你可以做这样的事情:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    dataObj = frc.object(at: indexPath) as! Data_Object 
    var pvc: UIViewController? 

    let obj = getControllerFor(type: dateObj.type) 
    obj.data = dataObj 
    obj.isFull = true 
    obj.delegate = self 
    pvc = obj as UIViewController 
    obj.modalPresentationStyle = .popover 
    let popPVC = pvc?.popoverPresentationController 
    popPVC?.sourceView = self.view 
    self.present(pvc!, animated: true, completion: nil) 
} 



func getControllerFor(type : String) -> SuperType? { 
    switch type { 
    case "X": return XVC() 
    case "Y": return YVC() 
    case "Z": return ZVC() 
    default: return nil 
    } 
} 

class SuperType {} 
class XVC: SuperType {} 
class YVC: SuperType {} 
class ZVC: SuperType {} 

理想情况下,type不是String,而是Enum

+0

谢谢你的时间:) –

2

您可以使用enum很好地完成此操作。你只需要让你的每个ViewController符合CustomViewController。

enum ViewControllers: String { 
    case x = "X" 
    case y = "Y" 
    case z = "Z" 

    func getViewController<T>(dataObj: Data_Object, delegate: YourDelegate?) -> T where T: UIViewController, T: CustomViewController { 
     let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: self.rawValue) as! T 
     viewController.data = dataObj 
     viewController.isFull = true 
     viewController.delegate = delegate 

     return viewController 
    } 
} 

protocol CustomViewController: class { 
    var data: Data_Object! { get set } 
    var isFull: Bool! { get set } 
    weak var delegate: YourDelegate? { get set } 
} 

你会再使用这样的:

if dataObj.type == "X" { 
    let vc: XVC = ViewControllers.x.getViewController(dataObj: dataObj, delegate: self) 
    pvc = vc 
}