在 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
)只需要使用这两个函数 appMovedToBackground
和 appMovedToForeground
当他们需要时。
问题:
但是,我仍然担心一件事。当我将观察者设置部分移动到 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 中以专门执行此操作。
背景:
我正在 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
)只需要使用这两个函数 appMovedToBackground
和 appMovedToForeground
当他们需要时。
问题:
但是,我仍然担心一件事。当我将观察者设置部分移动到 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 中以专门执行此操作。