Search code examples
iosswiftgenericsredundancy

Avoiding repeating code in swift


In following code, based on the string comparison I am deciding on which VC will be shown.

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)
}

Now, all of the code is repetitive except class name and I want to avoid that. But, swift do not have NSClassFromString

How do I accomplish this? Should I use Generics/Templates? Any suggestions!

Sorry in advance, if I am missing something silly here.


Solution

  • The removal of duplication is obvious:

    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
    

    Where PVC is the common superclass of your 3 controllers, e.g. :

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

    If your 3 classes don't have a common superclass, you can use a protocol instead:

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

    and implement it by your 3 classes:

    In short, to remove the duplication, you need to add a common interface to the 3 controllers. Either using a common superclass or protocol.