扩展UIViewController以访问应用程序委托是反模式吗?

时间:2019-02-05 17:35:41

标签: ios cocoa-touch appdelegate object-graph

我正在使用一个API,建议将其客户端保留在应用程序委托中并从那里访问它。如果我扩展了UIViewController以使其更易于访问应用程序委托,这是否是反模式?

extension UIViewController {
    var appDelegate: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
}

class SomeViewController: UIViewController {
    ...
    appDelegate.someClient.someMethod()
    ...
}

通过反模式,我的意思是,为这种简单的方便而扩展整个UIViewController类是否为时过早?像这样的扩展类,总体上是否有负面影响?每个视图控制器即使不访问API也会隐式指向应用程序委托吗?

2 个答案:

答案 0 :(得分:2)

  

如果我扩展了UIViewController以使其更易于访问该应用程序   代表,这是反模式吗?

extension UIViewController {
    var appDelegate: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    } 
}

否;恰恰相反。通常需要访问应用程序委托并将其强制转换为它的实际类,以便能够访问属性或在应用程序委托中调用方法。如果这可能需要在多个地方完成,则计算属性是提供速记的标准符号。 (无需为此目的使用扩展名,但这样做没有害处,并且可能会有符号上的优势;例如,该扩展名可以位于应用程序委托文件中。)


在注释中,您对扩展UIViewController的智慧深思。我想象您有两个需要访问应用程序委托的视图控制器,而其他许多不需要的。

现在,首先,这并不能真正改变我的答案。我看不到它会带来什么危害,或者看不到它如何成为一种反模式,使您所有的视图控制器都能够通过快捷方式访问应用程序委托,即使其中许多人实际上从未这样做过。所有视图控制器都已经具有执行很多的功能,而这些功能大多数都是他们实际上不会执行的。

但是,假设您有其他感觉。然后,您可以在每个相关的视图控制器中显式实现appDelegate(以违反DRY的代价)。

或者(这里是很酷的部分),您可以声明一个协议和一个协议扩展,并且只有相关的视图控制器才能采用它。因此,这是您的 AppDelegate.swift 文件:

import UIKit

protocol AppDelegateAccesser {}
extension AppDelegateAccesser {
    var appDelegate: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
}

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    // ....
}

现在让我们说实际上只有MyViewController类需要访问应用程序委托。那你就说

extension MyViewController : AppDelegateAccesser {}

这会将appDelegate注入MyViewController,但不会注入其他类。因此,您只需要为每个需要访问应用程序委托的视图控制器执行此操作,而无需执行其他操作。与您最初提出的解决方案相比,我认为这是完全不必要的练习,但是它确实解决了仅将代码注入某些类的问题。


注意:在Swift 5中,声明仅UIViewController子类可以采用此协议是合法的。您可能会喜欢。

答案 1 :(得分:0)

将此功能放到AppDelegate文件中,以便您可以在整个项目中访问AppDelegate。

class func shared() -> AppDelegate {
     return UIApplication.shared.delegate as! AppDelegate
}

您可以像这样使用:

AppDelegate.shared()