2016-08-23 42 views
2

开始我的第一个破解POP。在这种情况下,我想装饰一些UIViewControllers,以便他们自动引发“浏览页面”分析事件。面向协议的编程,隐式调用扩展方法

所以我创建了一个协议,并延长该协议:

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

这工作,因为我想,如果我装修的UIViewController与ReportPageViewedEvent这样的:

class HomeView: UIViewController, ReportPageViewedEvent { 

我得到一个编译器错误,除非我设置'pageName',这正是我想要的。

在哪里我越来越脱钩是在哪里以及如何调用实际reportPageViewed()方法。我真的希望它从viewDidLoad被调用,这意味着我要么在每个使用它的控制器中修改每个'viewDidLoad',要么在子类中调用超级类中的方法,这首先违反了POP的要点。

有没有一种很好的方法来实现这一点。在任何教程/博客中我找不到这样的例子。

+1

如果你想在每个ViewController中调用它,我会说子类化是最好的解决方案 – h345k34cr

+1

扩展为类添加了额外的功能,但不会使对象使用该功能。您需要手动调用它或使用传统的子类,以便可以覆盖继承的行为。此外,'viewWillAppear'可能是一个更好的报告点,因为ViewController实例只加载一次,但可能会多次提交 – Paulw11

+0

糟糕,无法在viewWillAppear上调用它。我试图遵循这个:http://krakendev.io/blog/subclassing-can-suck-and-heres-why但是在第一个障碍时,它已经脱落了。如果我能够自动调用它,因为装饰具有所需功能的类似乎是一种很好的方法。试图避免为此进行子类化。 –

回答

1

基本上,应用程序的所有屏幕总是会有一些行为共享。因此,创建一个名为(例如)BaseViewController的类是合适的,因此所有其他视图控制器都将从其继承。 在BaseViewController的viewDidLoad中,您可以调用reportPageViewed()方法。 但是,这种方法不需要面向协议的编程。当您需要将一些相同的行为分配给没有共同点的对象时(这不适用于应用程序屏幕),协议非常有用。