背景:

我正在使用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)仅在需要时使用这两个函数appMovedToBackgroundappMovedToForeground

问题:

但是,我仍然担心一件事。当我将观察者设置部分移到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")
     }
}

10-08 05:34