1

我的应用可以通过 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]
}

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

4

2 回答 2

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一旦应用程序真正进入前台,就安排一个侦听器进行身份验证。

于 2018-12-21T10:12:02.690 回答
0

正如您可以从Apple 官方文档中找到的那样

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

所以是的,这是正确的行为。

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

于 2018-12-21T08:42:48.293 回答