背景:
我正在使用iOS应用程序。我们大约有100个ViewControllers
,并且我们应用程序中的所有这些从一开始都是从BaseViewController
继承的。当前,在重构时,我看到许多视图控制器需要检测willEnterForegroundNotification
[1]和didEnterBackgroundNotification
[2]
代表去做一些内部任务。大约20〜25个视图控制器正在为其viewDidLoad
上的委托设置自己的通知观察者。我正在考虑将此检测任务移到中央BaseViewController
以便代码清晰。
我建议的解决方案:
我的预期设计如下
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToForeground), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: Notification.Name.UIApplicationDidEnterBackground, object: nil)
}
func appMovedToBackground() {
print("App moved to Background!")
}
func appMovedToForeground() {
print("App moved to ForeGround!")
}
}
class MyViewController: BaseViewController {
override func appMovedToBackground() {
print(“Do whatever need to do for current view controllers on appMovedToBackground”)
}
override func appMovedToForeground() {
print(“Do whatever need to do for current view controllers on appMovedToForeground”)
}
}
我看到,如果将这种检测移到
BaseViewController
,则子视图控制器将减少许多自定义观察者处理任务。子ViewController(即示例代码中的MyViewController
)仅在需要时使用这两个函数appMovedToBackground
和appMovedToForeground
。问题:
但是,我仍然担心一件事。当我将观察者设置部分移到
BaseViewController
时,所有ViewControllers
(在我的项目中大约有100个)将在默认的viewDidLoad
中注册观察者,并且其中许多甚至都不会在实际中使用它们。恐怕这种设计可能会严重影响应用性能。在这种情况下在性能与代码清晰度和可维护性之间进行权衡时,我的预期设计是否可以接受?我有没有更好的设计?参考:
[1] willEnterForegroundNotification-应用进入背景时发布。
[2] didEnterBackgroundNotification-在应用程序离开背景状态成为活动应用程序之前不久发布。
最佳答案
通知是一对多的交流。如果您确实不具备此功能。您可以使用协议委托方法。您只能在需要时分配委托。
为了解决您的问题,您可以将观察者移动到委托变量didSet中。因此,仅当您分配委托时,才会添加观察者。如果您未设置它,则不会为该viewController添加它。
@objc protocol AppActivityTracker{
func appMovedToBackground()
func appMovedToForeground()
}
class BaseViewController: UIViewController {
var activityDelegate : AppActivityTracker? {
didSet{
//MARK:-Observer will be added only when you assign delegate.
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToForeground), name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
class MyViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
//MARK:- Assign delegate only when you need observers
activityDelegate = self
}
}
//MARK:- Assign delegate only when you need observers
extension MyViewController : AppActivityTracker{
func appMovedToBackground() {
print("Do whatever need to do for current view controllers on appMovedToBackground")
}
func appMovedToForeground() {
print("Do whatever need to do for current view controllers on appMovedToForeground")
}
}
来自评论的讨论:-
在
viewWillAppear
上添加观察者,在viewDidDisappear
上移除观察者。@objc protocol AppActivityTracker{
func appMovedToBackground()
func appMovedToForeground()
}
class BaseViewController: UIViewController {
var activityDelegate : AppActivityTracker? {
didSet{
if activityDelegate != nil{
addOberservers()
}
else{
removeOberservers()
}
}
}
func addOberservers(){
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToForeground), name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(activityDelegate?.appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
func removeOberservers(){
let notificationCenter = NotificationCenter.default
notificationCenter.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
}
}
class MyViewController: BaseViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//MARK:- Assign delegate only when you need observers
self.activityDelegate = self
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
//MARK:- Removing observer on view will disappear.
self.activityDelegate = nil
}
}
//MARK:- Assign delegate only when you need observers
extension MyViewController : AppActivityTracker{
func appMovedToBackground() {
print("Do whatever need to do for current view controllers on appMovedToBackground")
}
func appMovedToForeground() {
print("Do whatever need to do for current view controllers on appMovedToForeground")
}
}