2

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.

wonea
  • 4,783
  • 17
  • 86
  • 139
Si-N
  • 1,495
  • 1
  • 13
  • 27
  • 1
    If you want it in every ViewController to be called I'd say subclassing is the best solution – h345k34cr Aug 23 '16 at 13:57
  • 1
    An extension adds additional capabilities to a class, but does not make objects use that capability. You either need to call it manually or use traditional subclassing so that you can override the inherited behaviour. Also, `viewWillAppear` might be a better reporting point as a ViewController instance is only loaded once but may be presented many times – Paulw11 Aug 23 '16 at 14:03
  • Oops, silly mistake on not calling it on viewWillAppear. I was trying to follow this: http://krakendev.io/blog/subclassing-can-suck-and-heres-why but came unstuck at the first hurdle. Would of been ideal if I could of called it automatically as decorating classes with needed functionality seems like a good approach. Was trying to avoid subclassing for this. – Si-N Aug 23 '16 at 14:05
  • 1
    POP is a class composition technique. While it offers many of the same results as multiple inheritance it can't override inherited behaviour. For that you need to subclass – Paulw11 Aug 23 '16 at 14:07
  • Ok, so in this case POP just isn't suitable? It's annoying because I'm 90% of the way to making a nice reusable protocol extension, but the only way I can make method call implicit is by subclassing, which means I might as well do away with the POP part altogether. – Si-N Aug 23 '16 at 14:10
  • Correct. This is not a situation where POP will help. – Paulw11 Aug 23 '16 at 14:18

1 Answers1

1

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

Max Pevsner
  • 4,098
  • 2
  • 18
  • 32