扩展 UIViewController 以访问应用委托是一种反模式吗?
Is extending UIViewController to access the app delegate an antipattern?
我使用的 API 建议将其客户端保留在应用委托中并通过那里访问它。如果我扩展 UIViewController
以使其更容易访问应用程序委托,这是否是一种反模式?
extension UIViewController {
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
}
class SomeViewController: UIViewController {
...
appDelegate.someClient.someMethod()
...
}
我所说的反模式是指为了这个简单的方便而扩展整个 UIViewController
class 是不是太过分了?总体而言,像这样扩展 classes 是否有任何负面影响?是否每个视图控制器,即使它不访问 API,现在都隐式指向应用程序委托?
If I extended UIViewController to make it easier to access the app
delegate, is this any way an antipattern?
extension UIViewController {
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
}
没有;恰恰相反。需要访问应用程序委托并将其转换为实际的 class 以便能够访问 属性 或调用应用程序委托中的方法是很常见的。如果这可能需要在多个地方完成,计算的 属性 是提供 shorthand 的标准符号。 (不需要为此目的使用扩展,但这样做没有坏处,并且可能有符号优势;例如,扩展可以位于应用程序委托文件中。)
在评论中,您思考扩展 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 class 实际上需要访问应用程序委托。那你就说
extension MyViewController : AppDelegateAccesser {}
这会将 appDelegate
注入 MyViewController 但不会注入其他 class。因此,您只需为每个需要访问应用程序委托的视图控制器执行此操作,而不是其他人。我认为这是一个完全不必要的练习,与您最初提出的解决方案相反,但它确实解决了仅将代码注入某些 classes 的问题。
注意:在 Swift5 中声明只有 UIViewController subclass 可以采用此协议是合法的。你可能会喜欢。
将此函数放入 AppDelegate 文件,以便您可以在整个项目中访问 AppDelegate。
class func shared() -> AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
你可以像这样使用:
AppDelegate.shared()
我使用的 API 建议将其客户端保留在应用委托中并通过那里访问它。如果我扩展 UIViewController
以使其更容易访问应用程序委托,这是否是一种反模式?
extension UIViewController {
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
}
class SomeViewController: UIViewController {
...
appDelegate.someClient.someMethod()
...
}
我所说的反模式是指为了这个简单的方便而扩展整个 UIViewController
class 是不是太过分了?总体而言,像这样扩展 classes 是否有任何负面影响?是否每个视图控制器,即使它不访问 API,现在都隐式指向应用程序委托?
If I extended UIViewController to make it easier to access the app delegate, is this any way an antipattern?
extension UIViewController { var appDelegate: AppDelegate { return UIApplication.shared.delegate as! AppDelegate } }
没有;恰恰相反。需要访问应用程序委托并将其转换为实际的 class 以便能够访问 属性 或调用应用程序委托中的方法是很常见的。如果这可能需要在多个地方完成,计算的 属性 是提供 shorthand 的标准符号。 (不需要为此目的使用扩展,但这样做没有坏处,并且可能有符号优势;例如,扩展可以位于应用程序委托文件中。)
在评论中,您思考扩展 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 class 实际上需要访问应用程序委托。那你就说
extension MyViewController : AppDelegateAccesser {}
这会将 appDelegate
注入 MyViewController 但不会注入其他 class。因此,您只需为每个需要访问应用程序委托的视图控制器执行此操作,而不是其他人。我认为这是一个完全不必要的练习,与您最初提出的解决方案相反,但它确实解决了仅将代码注入某些 classes 的问题。
注意:在 Swift5 中声明只有 UIViewController subclass 可以采用此协议是合法的。你可能会喜欢。
将此函数放入 AppDelegate 文件,以便您可以在整个项目中访问 AppDelegate。
class func shared() -> AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
你可以像这样使用:
AppDelegate.shared()