【问题标题】:Handling applicationDidBecomeActive - "How can a view controller respond to the app becoming Active?"处理 applicationDidBecomeActive - “视图控制器如何响应应用程序变为活动状态?”
【发布时间】:2011-04-08 01:54:49
【问题描述】:

我的主 AppDelegate.m 类中有 UIApplicationDelegate 协议,并定义了 applicationDidBecomeActive 方法。

我想在应用程序从后台返回时调用一个方法,但该方法在另一个视图控制器中。如何检查 applicationDidBecomeActive 方法中当前显示的视图控制器,然后调用该控制器中的方法?

【问题讨论】:

    标签: ios iphone ios4 multitasking uiapplicationdelegate


    【解决方案1】:

    对于 Swift5 MacOS,您需要使用 NSApplication 而不是 UIApplication。

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(applicationDidBecomeActive),
                                           name: (NSApplication.didBecomeActiveNotification),
                                           object: nil)
        }
    

    【讨论】:

      【解决方案2】:

      在 Swift 5 中

      override func viewWillAppear(_ animated: Bool) {
               super.viewWillAppear(animated)
      
               NotificationCenter.default.addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
          
               NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
              }
          
          override func viewWillDisappear(_ animated: Bool) { 
              super.viewWillDisappear(animated)
      
              NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
      
              NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
          }
      
      
      @objc private func applicationWillResignActive() {
          }
      
          @objc private func applicationDidBecomeActive() {
          }
      

      【讨论】:

        【解决方案3】:

        如果你们中的任何人正在使用 SwiftUI:

        .onReceive(NotificationCenter.default.publisher(
            for: UIApplication.didBecomeActiveNotification)) { _ in
                print("DID BECOME ACTIVE")
            }
        )
        

        【讨论】:

          【解决方案4】:

          Swift 5 版本:

           NotificationCenter.default.addObserver(self,
                                                         selector: #selector(loadData),
                                                         name: UIApplication.didBecomeActiveNotification,
                                                         object: nil)
          

          在 iOS 9 及更高版本中删除观察者 is no longer required

          【讨论】:

            【解决方案5】:

            组合方式:

            import Combine
            
            var cancellables = Set<AnyCancellable>()
            NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
                .sink { notification in
                        // do stuff
                }.store(in: &cancellables)
            

            【讨论】:

              【解决方案6】:

              斯威夫特 5

              fileprivate  func addObservers() {
                    NotificationCenter.default.addObserver(self,
                                                           selector: #selector(applicationDidBecomeActive),
                                                           name: UIApplication.didBecomeActiveNotification,
                                                           object: nil)
                  }
              
              fileprivate  func removeObservers() {
                      NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
                  }
              
              @objc fileprivate func applicationDidBecomeActive() {
              // here do your work
                  }
              

              【讨论】:

                【解决方案7】:

                Swift 3、4 等效项:

                添加观察者

                NotificationCenter.default.addObserver(self,
                    selector: #selector(applicationDidBecomeActive),
                    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
                    object: nil)
                

                移除观察者

                NotificationCenter.default.removeObserver(self,
                    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
                    object: nil)
                

                回调

                @objc func applicationDidBecomeActive() {
                    // handle event
                }
                

                【讨论】:

                • 我在哪里称呼这个?
                • @user8169082,您可以在需要开始接收通知的任何地方添加观察者。例如,您可以将其添加到 viewDidLoadviewWillAppear:animated。当您不再需要通知时,或者当您的观察者实例将在 deinit 方法中被释放时,您可以移除观察者
                • swift 4.2 我正在使用:NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(notification:)), name: UIApplication.didBecomeActiveNotification, object: nil)
                【解决方案8】:

                斯威夫特 4.2

                添加观察者-

                NotificationCenter.default.addObserver(self, selector: #selector(handleEvent), name: UIApplication.didBecomeActiveNotification, object: nil)
                

                移除观察者-

                NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
                

                处理事件-

                @objc func handleEvent() {
                }
                

                【讨论】:

                  【解决方案9】:

                  对于 Swift 4,Apple 通过新的编译器警告建议我们避免在这种情况下使用 #selector。以下是实现此目的的更安全的方法:

                  首先,创建一个可以被通知使用的惰性变量:

                  lazy var didBecomeActive: (Notification) -> Void = { [weak self] _ in
                      // Do stuff
                  } 
                  

                  如果您需要包含实际通知,只需将 _ 替换为 notification

                  接下来,我们设置通知以观察应用是否处于活动状态。

                  func setupObserver() {
                      _ = NotificationCenter.default.addObserver(forName: .UIApplicationDidBecomeActive,
                                                                 object: nil,
                                                                 queue:.main,
                                                                 using: didBecomeActive)
                  }
                  

                  这里最大的变化是,我们现在调用上面创建的 var,而不是调用 #selector。这可以消除出现无效选择器崩溃的情况。

                  最后,我们移除观察者。

                  func removeObserver() {
                      NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
                  }
                  

                  【讨论】:

                  • #selector 可以调用在 Swift 4 中声明为 @objc 属性的方法。
                  • 使用removeObserver(self是不正确的,因为添加观察者时没有分配self。你应该let observer = NotificationCenter.default.addObserver 然后removeObserver(observer
                  • 谢谢@CodeBender 我还不知道这个功能,它(最终)删除了@objc。但是,当我尝试它时,我在控制台中收到警告(Xcode 11.3.1 (11C504)、Swift 13.3):无法结束 BackgroundTask:不存在带有标识符的后台任务。 即使我保存了变量中的观察者作为 NSObjectProtocol。
                  • 没关系,如果我使用 @objc 变体,我也会收到警告。
                  【解决方案10】:

                  应用程序中的任何类都可以成为应用程序中不同通知的“观察者”。当您创建(或加载)您的视图控制器时,您需要将其注册为 UIApplicationDidBecomeActiveNotification 的观察者,并指定当通知发送到您的应用程序时要调用的方法。

                  [[NSNotificationCenter defaultCenter] addObserver:self
                                                           selector:@selector(someMethod:)
                                                               name:UIApplicationDidBecomeActiveNotification object:nil];
                  

                  别忘了自己打扫卫生!当您的视图消失时,请记住将自己移除为观察者:

                  [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                                  name:UIApplicationDidBecomeActiveNotification
                                                                object:nil];
                  

                  更多关于Notification Center的信息。

                  【讨论】:

                  • 优秀。没想到用NSNotificationCenter。谢谢!
                  • 只是该行代码中的一个错字(缺少“名称”):[[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(someMethod:) name:UIApplicationDidBecomeActiveNotification object:nil];
                  • 要添加到 Reed 的答案中,被调用的方法(在本例中为 someMethod)需要接受 NSNotification 参数。所以 someMethod 的方法签名是 -(void)someMethod:(NSNotification *)notification { //Do Something Here }
                  • @Aaron 可以,但这不是必需的。不过,这是很好的洞察力。谢谢!
                  • 太棒了!在视图控制器/负责这些 NSTimer 的其他对象中,一种使 NSTimer 实例无效/重新创建的好方法。喜欢它!
                  【解决方案11】:

                  Swift 2 等效项

                  let notificationCenter = NSNotificationCenter.defaultCenter()
                  
                  // Add observer:
                  notificationCenter.addObserver(self,
                    selector:Selector("applicationWillResignActiveNotification"),
                    name:UIApplicationWillResignActiveNotification,
                    object:nil)
                  
                  // Remove observer:
                  notificationCenter.removeObserver(self,
                    name:UIApplicationWillResignActiveNotification,
                    object:nil)
                  
                  // Remove all observer for all notifications:
                  notificationCenter.removeObserver(self)
                  
                  // Callback:
                  func applicationWillResignActiveNotification() {
                    // Handle application will resign notification event.
                  }
                  

                  【讨论】:

                  • 在 Swift 中放置 removeObserver 的最佳位置:deinit 方法。
                  • 一般不建议在deinit中访问self;此时,self 处于完全分配和解除分配之间
                  • 那么你会在哪里移除Observer?
                  • @EnricoSusatyo 你可以忽略它,因为它不正确。覆盖 deinit 很好:“因为实例在其 deinitializer 被调用后才被释放,所以 deinitializer 可以访问它被调用的实例的所有属性,并且可以根据这些属性修改其行为(例如查找需要关闭的文件)。” 调用deinit不行
                  • 如果您的应用面向 iOS 9.0 及更高版本或 macOS 10.11 及更高版本,则无需移除观察者。系统会清理它。供参考,developer.apple.com/documentation/foundation/notificationcenter/…
                  猜你喜欢
                  • 1970-01-01
                  • 2012-05-08
                  • 2018-05-31
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多