在 iOS 中检测 foreground/background 代表的适当位置是什么?

What are proper places to detect foreground/background delegates in iOS?

背景:

我正在 iOS 应用程序中工作。我们有大约 100 个 ViewControllers,我们应用程序中的所有这些都是从一开始就继承自 BaseViewController。目前在重构时,我看到许多视图控制器需要检测 willEnterForegroundNotification[1] and 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,则子视图控制器中的许多自定义观察者处理任务都会减少。子视图控制器(即示例代码中的 MyViewController)只需要使用这两个函数 appMovedToBackgroundappMovedToForeground 当他们需要时。

问题:

但是,我仍然担心一件事。当我将观察者设置部分移动到 BaseViewController 时,因此所有 ViewControllers(我的项目中大约有 100 个)将在其默认值 viewDidLoad 中注册观察者,其中许多人不会'甚至不要在现实中使用它们。恐怕这种设计可能会严重影响应用程序性能。在这种情况下,在性能与代码清晰度和可维护性之间进行权衡时,我的预期设计是否可以接受?我的情况还有更好的设计吗?


参考:

[1] willEnterForegroundNotification - 在应用进入后台时发布。

[2] didEnterBackgroundNotification - 在应用程序离开后台状态成为活动应用程序之前不久发布。

您可以声明一个协议让我们调用它 BGFGObserver。 让前台、后台每一个需要观察的VC对这个协议进行确认。 在 base class 中检查 self 是否确认 BGFGObserver,如果是则仅注册为观察者。 在 BGFGObserver 中,您将需要有处理背景和前景的方法。

通知是一对多的通信。如果你真的没有这个功能。您可以使用协议委托方法。您可以仅在需要时分配委托。

为了解决您的问题,您可以将观察者移动到委托变量的 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")
     }
}

您可以在 AppDelegate 中执行此操作,或者创建一个单独的 class 保存在 AppDelegate 中以专门执行此操作。