我的 iPhone 应用程序在某些设备上收到推送通知后崩溃(尤其是 ios_10.3.1)

My iPhone App crashes after getting push notification in some devices(especially ios_10.3.1)

我刚刚弄清楚如何在我的应用程序中正确发送推送通知。然而,当它开始正常工作时,出现了一种新的错误类型。我的应用程序在收到推送通知后启动时崩溃。我在 5 台设备上进行了测试,其中 2 台由于这个问题而崩溃了(都是 iOS_10.3.1 上的 运行)。奇怪的是其他 3 台设备在 iOS 10.2 和 9.3.1 上 运行。我真的不认为这与 OS 有关。

Apple 已经发送了这样的崩溃日志,但是当我单击“在项目中打开”时,它只会打开我的启动屏幕 xib

我的appDelegate class APNS服务调用部分->

 func registerForPushNotifications(application: UIApplication)
{

    if #available(iOS 10.0, *){
        UNUserNotificationCenter.currentNotificationCenter().delegate = self
        UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert], completionHandler: {(granted, error) in
            if (granted)
            {
                UIApplication.sharedApplication().registerForRemoteNotifications()
            }
            else{
                CommonViewController.alertViewUI("Alert", message: "Push notification is enabled")
            }
        })
    }

    else{ //If user is not on iOS 10 use the old methods we've been using
        let notificationSettings = UIUserNotificationSettings(
            forTypes: [.Badge, .Sound, .Alert], categories: nil)
        application.registerUserNotificationSettings(notificationSettings)

    }

}

我的应用程序正常运行-> 启动时------------------------

版本检查 class 以了解用户 version.From 在那里它被重定向到主页面。

在首页-> 1. 加载视图。 2. 异步调用 link 并获取要显示在警报符号附近的可用通知计数。(我很确定调用此 link 或获取通知时没有错误)---- ----------------------

注意: ** 当双击 iPhone 主页按钮菜单时,应用程序在后台显示为打开的屏幕,主页打开(崩溃后)。

**一台 10.3.1 设备正常工作

**如果重新安装应用程序,一切正常。

请检查您在此处所写的内容,因为此功能是在收到推送通知时调用的。请对此进行调试。

func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { }

  • 此代码解决了您的问题::-

    func registerPushNotifications() {
    
     if #available(iOS 10.0, *) {
        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil{
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    else {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
    }
    

如果我的理解是正确的,您的应用程序正在移至后台并在返回前台时崩溃。

这看起来不像是 UNUserNotifications 的问题。在这种情况下,更像是通知只会触发您的应用程序崩溃。 Stack 显示崩溃发生在您的应用程序中。这意味着当返回到前台时,您 运行 在某处的空指针引用上。
盲猜:
你在听 UIApplicationDidBecomeActiveNotification 还是 UIApplicationWillEnterForegroundNotification?
如果是,则每个 class 收听这些通知的人都需要在遇到垃圾收集器之前取消订阅。这样做的好地方是 dealloc/deinit.

自从您使用 Swift:

deinit {
    NotificationCenter.default.removeObserver(self)
}

Objective-C ARC 看起来像:

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

如果它不收听通知,那么它仍然是某处被释放的引用。它没有立即崩溃的原因是一个简单的僵尸。即将被释放的对象实例,但在某些设备上的运行时还没有释放。

对我来说,它是在请求导致崩溃的授权之前设置 UNUserNotificationCenter.current() 的委托。这就是我修复它的方式。希望对其他人有所帮助。

func registerForPushNotifications() {
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.sound, .alert, .badge]) { [weak self] granted, _ in
        print("Permission granted: \(granted)")
        guard granted else { return }
        center.delegate = self
        self?.getNotificationSettings()
    }
}

func getNotificationSettings() {
  UNUserNotificationCenter.current().getNotificationSettings { settings in
    print("Notification settings: \(settings)")
      guard settings.authorizationStatus == .authorized else { return }
      DispatchQueue.main.async {
        UIApplication.shared.registerForRemoteNotifications()
      }
  }
}