How to re-define a protocol extension from a child view controller

Viewed 105

I have a protocol with an extension that defines the functions:

protocol DataFetch where Self: UIViewController {
    var data: [SomeData]! { get set }
    func fetchData()
    func didFetch()
}

extension DataFetch {
    func fetchData() {
        /// fetch data
    }
    func didFetch() {
        /// do something after fetching data
    }
}

Then, I have a view controller that conforms to the protocol as well as a child view controller that inherits from the parent view controller:

class ParentViewController: UIViewController, DataFetch {
    var data: [SomeData]! {
        didSet {
            didFetch()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData()
    }
}

class ChildViewController: ParentViewController {
    func didFetch() {
        /// do something else
    }
}

I would like to override one of the inherited functions in the child view controller, but since you cannot do that with a protocol extension, I tried to simply re-define the function definition. But, I find that the re-defined function in the child view controller doesn't get called within didSet.

1 Answers

This is more of a workaround but since didSet seems to only handle the current scope (ParentViewController) and not sees what is defined in the ChildViewController and also since you can not use the override keyword when implementing didFetch in the ChildViewController to force it to be used this solution introduces a new function so we can make override to work as expected

First create a new function in the parent controller and call it from didSet as below

class ParentViewController: UIViewController, DataFetch {
    var data: [String]! {
        didSet {
            workaround()
        }
    }

    func workaround() {
        didFetch()
    }
    //...
}

and now override this function in the child controller and the correct didFetch will be called

class ChildViewController: ParentViewController {
    override func workaround() {
        didFetch()
    }
    //...
}
Related