Search code examples
iosswiftuiviewcontrollerprotocol-oriented

Protocol Oriented Programming, implicitly calling extension method


Having my first crack at POP. In this case I want to decorate some UIViewControllers so that any that they automatically raise a 'Page viewed' analytics event.

So I created a protocol, and and extension for that protocol:

protocol ReportPageViewedEvent {
    func reportPageViewed()
    var pageName : String? { get set }
}

extension ReportPageViewedEvent where Self: UIViewController
{
    func reportPageViewed()
    {
        guard let pageName = self.pageName else
        {
            fatalError("UIViewController implements ReportPageViewEvent protocol but did not set pageName property")
        }
        let eventBusiness = EventBusiness.sharedInstance
        eventBusiness.logUserViewedPage(pageName)
    }
}

This works as I want, if I decorate a UIViewController with ReportPageViewedEvent like this:

class HomeView: UIViewController, ReportPageViewedEvent {

I get a compiler error unless I set 'pageName' which is exactly what I want.

Where I am getting unstuck is where and how to call the actual reportPageViewed() method. I really want it to be called from viewDidLoad which means I either have to modify every 'viewDidLoad' in every controller that uses it, or subclass and call the method in the super class which defies the point of using POP in the first place.

Is there a nice way to achieve this. I can't find an example like this in any tutorial/blog.


Solution

  • Basically, there is always some behaviour shared by all the screens of your app. So it is appropriate to create a class called (for example) BaseViewController so all the other view controllers will inherit from it. In BaseViewController's viewDidLoad you can call the reportPageViewed() method. However, this approach makes the Protocol Oriented Programming not needed. Protocols are useful when you need to assign some same behaviour to objects that have nothing in common (which is not the case for app screens).