Search code examples
iosswiftswift5xcode11

How do I implement abstract methods with different parameters/return types


I have parent class called "Item", and child class called "YTListItem". I want to have a functions called instantiate() which will be implemented in each child class, and return a view controller. The type of the view controller will be different depending on which child class is calling the instantiate() method. My issue is that swift does not seem to recognize me overriding the function if it has different parameters or return types.

The error occurs when I override the function, I get the error "Method does not override any method from its superclass".

class Item {
    var name: String
    var description: String

    init(name: String = "Test text", description: String = "Test description of the item") {
        self.name = name
        self.description = description
    }

    func instantiate() {}



}



class YTListItem: Item {
    var address: String

    init(name: String = "Test text", description: String = "Test text", address: String = "SivTGfXxYz0") {
        self.address = address
        super.init(name: name, description: description)
    }

     override func instantiate(storyboard: UIStoryboard) -> YTDescViewController? {
        let vc = storyboard.instantiateViewController(identifier: "desc") as? YTDescViewController
        return vc
    }

}

Is there a way to do this? I've seen mentions of protocols when searching how to make it work but I'm new to swift so I'm hoping to be able to get through it using methods I've already learned.


Solution

  • First of all I don't think you should be instantiating a ViewController from you model class. Instead you should be injecting your model to the ViewController. But for your particular scenario you can just return a UIViewController from instantiate function rather than it's subclass (YTDescViewController). And I think you should use protocols for your scenario something like this:

    protocol Item {
       var name: String {get set}
       var description: String {get set}
       var storyboard : UIStoryboard {get set}
       func instatntiate() -> UIViewController
    }
    extension Item {
       var viewControllerID : String {
           return "desc"
       }
    }
    struct YTListItem:  Item {
       var name: String
       var description: String
       var storyboard: UIStoryboard
       func instatntiate() -> UIViewController {
          return storyboard.instantiateViewController(identifier: viewControllerID)
       }
    
    }
    

    You can also use associatedType to customize the return type of instantiate (or the parameters) in Item protocol. But in that case you would need to implement type erasures to hold generic reference to class/struct objects that implement Item protocol.