PushKit背景通知在初始视图控制器上触发viewDidAppear

时间:2018-12-21 08:18:58

标签: ios swift apple-push-notifications pushkit

我的应用程序可以通过PushKit接收后台通知。这些PushKit通知会触发一项操作,以清理先前传递的常规通知。

当我终止应用程序并收到PushKit通知时,我的初始视图控制器(在情节提要中配置)会触发viewDidAppear。这给我造成了一些问题。我知道PushKit在后台启动您的应用程序,但是我不明白为什么viewDidAppear会被触发。因为该应用实际上从未打开过。

伪AppDelegate.swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    voipRegistration()
    Messaging.messaging().delegate = self

    // setup Firebase/Bugfender

    UNUserNotificationCenter.current().delegate = self
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) {granted, _ in
        // setup regular notifications
    }

    application.registerForRemoteNotifications()
    return true
}

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: identifiers)
}

func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
    // register token with server
}

fileprivate func voipRegistration() {
    let voipRegistry = PKPushRegistry(queue: nil)

    voipRegistry.delegate = self
    voipRegistry.desiredPushTypes = [.voIP]
}

我想知道是否通过PushKit触发viewDidAppear是否是正常行为?初始控制器中的viewDidAppear启动了我的身份验证过程,我不希望在应用程序处于后台时发生这种情况。

2 个答案:

答案 0 :(得分:1)

如发布的@fewlinesofcode链接中所述,viewDidAppear在实际出现在屏幕上时不会触发,而是在将其添加到视图控制器层次结构时触发。因此,这会在启动时触发。

我使用UIApplication.shared.applicationState解决了这个问题,就像这样:

伪AppDelegate.swift:

    func applicationWillEnterForeground(_ application: UIApplication) {
        center.post(name: .ApplicationWillEnterForeground, object: self, userInfo: nil)
    }

伪BaseViewController.swift:

class BaseViewController: UIViewController {
    var applicationWillEnterForegroundObserver: NSObjectProtocol?
    let center = NotificationCenter.default

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if UIApplication.shared.applicationState != .background {
            authenticate()
        } else {
            if applicationWillEnterForegroundObserver == nil {
                applicationWillEnterForegroundObserver = center.addObserver(
                    forName: .ApplicationWillEnterForeground,
                    object: nil, queue: nil) { (_) in
                        self.center.removeObserver(self.applicationWillEnterForegroundObserver!)     
                        self.authenticate()
                    }
            }
        }
    }

    fileprivate func authenticate() {
        // do authentication logic
    }
}

这会在viewDidAppear中检查应用程序是否在后台运行(例如PushKit启动应用程序时)。如果没有,只需进行身份验证并继续。如果是这样,请为applicationWillEnterForeground安排一个监听器,以在应用程序真正出现在前台时立即进行身份验证。

答案 1 :(得分:0)

您可以从Apple official documentation

中找到
  

在收到PushKit通知后,如果应用未运行,系统会自动启动。相比之下,不能保证用户通知会启动您的应用。

是的,这是正确的行为。

UPD:关键是,在收到PushKit通知后,该应用程序将被唤醒。应用程序一旦运行,就会有一定的执行时间,并且您的代码也正在执行。