应用程序未 运行 时的远程推送通知崩溃
Remote Push Notification when App is not running crashes
如果我发送远程推送通知,后台/前台一切正常。但是,如果我终止我的应用程序并想要处理推送通知,该应用程序将在几毫秒后启动并崩溃。
这是我的 didFinishLaunchingWithOptions
函数:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UNUserNotificationCenter.current().requestAuthorization(options:
[[.alert, .sound, .badge]],
completionHandler: { (granted, error) in
// Handle Error
})
application.registerForRemoteNotifications()
if let options: NSDictionary = launchOptions as NSDictionary? {
let remoteNotification =
options[UIApplicationLaunchOptionsKey.remoteNotification]
if let notification = remoteNotification {
self.application(application, didReceiveRemoteNotification:
notification as! [AnyHashable : Any],
fetchCompletionHandler: { (result) in
})
}
}
return true
}
还有我的didReceiveRemoteNotification
函数
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let tabBar: UITabBarController = self.window?.rootViewController as! UITabBarController
let navController: UINavigationController = tabBar.viewControllers![1] as! UINavigationController
let viewController = navController.viewControllers[0] as! CompanyProfileTableViewController
//let viewController = tabBar.viewControllers![1] as! CompanyProfileTableViewController
let notification: CKNotification = CKNotification(fromRemoteNotificationDictionary:
userInfo as! [String : NSObject])
print("\(notification)")
if (notification.subscriptionID == "company-changed") {
let queryNotification =
notification as! CKQueryNotification
print("\(queryNotification)")
let recordID = queryNotification.recordID
viewController.fetchRecord(recordID!)
}
}
我处理这个问题已经有足够多的时间了,但找不到合适的解决方案。我也检查了
Handling Push Notifications when App is NOT running
如果我重新启动该应用程序,则会对标签进行由 rPN 引起的更改。由于我必须终止该应用程序,所以我无法在 Xcode 中调试代码,同时将 rPN 发送到已终止的应用程序。
这是获取记录和更新标签的函数
//Fetch records from DB
func fetchRecord(_ recordID: CKRecordID) -> Void {
let privateDatabase = CKContainer.default().privateCloudDatabase
var recordIDArray: [CKRecordID] = []
recordIDArray.append(recordID)
let fetchRecordsWithID = CKFetchRecordsOperation(recordIDs: recordIDArray)
fetchRecordsWithID.fetchRecordsCompletionBlock = { (records, error) in
if error != nil {
print("Error")
} else {
DispatchQueue.main.async() {
self.currentRecord = records?[recordID]
let data = NSKeyedArchiver.archivedData(withRootObject: self.currentRecord ?? "none")
UserDefaults.standard.set(data, forKey: "companyRecord")
UserDefaults.standard.synchronize()
if let retrivedData = UserDefaults.standard.object(forKey: "companyRecord") {
let companyRecord = NSKeyedUnarchiver.unarchiveObject(with: retrivedData as! Data) as! CKRecord
self.companyNameLabel.text = companyRecord["companyName"] as? String
self.companyStreetLabel.text = companyRecord["companyStreet"] as? String
self.companyZipCodeLabel.text = companyRecord["companyZipCode"] as? String
}
}
}
}
privateDatabase.add(fetchRecordsWithID)
}
跟踪堆栈:
Trace Stack
我想问题出在获取记录功能上。
错误:
; partial apply forwarder for Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never).(closure #2)
0x1003d11e4 <+96>: nop
0x1003d11e8 <+100>: mov x0, x25
0x1003d11ec <+104>: mov x1, x24
0x1003d11f0 <+108>: mov x2, x23
0x1003d11f4 <+112>: mov x4, x8
0x1003d11f8 <+116>: bl 0x1002c4b80 ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
-> 0x1003d11fc <+120>: brk #0x1
我终于找到了解决办法。问题是我的 fetchRecord 函数。使用 "killed" 应用执行 rPN 时标签未初始化。
所以有两种方法可以解决这个问题:
第一名:
修改didReceiveRemoteNotification
方法:
if (notification.subscriptionID == "company-changed") {
let queryNotification =
notification as! CKQueryNotification
print("\(queryNotification)")
let recordID = queryNotification.recordID
tabBar.selectedIndex = 1
viewController.fetchRecord(recordID!)
}
我加这个->
tabBar.selectedIndex = 1
这将显示 viewController 并且标签已正确初始化。
另一个解决方案是将我用新值设置标签的部分放入 viewWillAppear 或 viewDidLoad。
如果我发送远程推送通知,后台/前台一切正常。但是,如果我终止我的应用程序并想要处理推送通知,该应用程序将在几毫秒后启动并崩溃。
这是我的 didFinishLaunchingWithOptions
函数:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UNUserNotificationCenter.current().requestAuthorization(options:
[[.alert, .sound, .badge]],
completionHandler: { (granted, error) in
// Handle Error
})
application.registerForRemoteNotifications()
if let options: NSDictionary = launchOptions as NSDictionary? {
let remoteNotification =
options[UIApplicationLaunchOptionsKey.remoteNotification]
if let notification = remoteNotification {
self.application(application, didReceiveRemoteNotification:
notification as! [AnyHashable : Any],
fetchCompletionHandler: { (result) in
})
}
}
return true
}
还有我的didReceiveRemoteNotification
函数
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let tabBar: UITabBarController = self.window?.rootViewController as! UITabBarController
let navController: UINavigationController = tabBar.viewControllers![1] as! UINavigationController
let viewController = navController.viewControllers[0] as! CompanyProfileTableViewController
//let viewController = tabBar.viewControllers![1] as! CompanyProfileTableViewController
let notification: CKNotification = CKNotification(fromRemoteNotificationDictionary:
userInfo as! [String : NSObject])
print("\(notification)")
if (notification.subscriptionID == "company-changed") {
let queryNotification =
notification as! CKQueryNotification
print("\(queryNotification)")
let recordID = queryNotification.recordID
viewController.fetchRecord(recordID!)
}
}
我处理这个问题已经有足够多的时间了,但找不到合适的解决方案。我也检查了
Handling Push Notifications when App is NOT running
如果我重新启动该应用程序,则会对标签进行由 rPN 引起的更改。由于我必须终止该应用程序,所以我无法在 Xcode 中调试代码,同时将 rPN 发送到已终止的应用程序。
这是获取记录和更新标签的函数
//Fetch records from DB
func fetchRecord(_ recordID: CKRecordID) -> Void {
let privateDatabase = CKContainer.default().privateCloudDatabase
var recordIDArray: [CKRecordID] = []
recordIDArray.append(recordID)
let fetchRecordsWithID = CKFetchRecordsOperation(recordIDs: recordIDArray)
fetchRecordsWithID.fetchRecordsCompletionBlock = { (records, error) in
if error != nil {
print("Error")
} else {
DispatchQueue.main.async() {
self.currentRecord = records?[recordID]
let data = NSKeyedArchiver.archivedData(withRootObject: self.currentRecord ?? "none")
UserDefaults.standard.set(data, forKey: "companyRecord")
UserDefaults.standard.synchronize()
if let retrivedData = UserDefaults.standard.object(forKey: "companyRecord") {
let companyRecord = NSKeyedUnarchiver.unarchiveObject(with: retrivedData as! Data) as! CKRecord
self.companyNameLabel.text = companyRecord["companyName"] as? String
self.companyStreetLabel.text = companyRecord["companyStreet"] as? String
self.companyZipCodeLabel.text = companyRecord["companyZipCode"] as? String
}
}
}
}
privateDatabase.add(fetchRecordsWithID)
}
跟踪堆栈:
Trace Stack
我想问题出在获取记录功能上。
错误:
; partial apply forwarder for Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never).(closure #2)
0x1003d11e4 <+96>: nop
0x1003d11e8 <+100>: mov x0, x25
0x1003d11ec <+104>: mov x1, x24
0x1003d11f0 <+108>: mov x2, x23
0x1003d11f4 <+112>: mov x4, x8
0x1003d11f8 <+116>: bl 0x1002c4b80 ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
-> 0x1003d11fc <+120>: brk #0x1
我终于找到了解决办法。问题是我的 fetchRecord 函数。使用 "killed" 应用执行 rPN 时标签未初始化。
所以有两种方法可以解决这个问题:
第一名:
修改didReceiveRemoteNotification
方法:
if (notification.subscriptionID == "company-changed") {
let queryNotification =
notification as! CKQueryNotification
print("\(queryNotification)")
let recordID = queryNotification.recordID
tabBar.selectedIndex = 1
viewController.fetchRecord(recordID!)
}
我加这个->
tabBar.selectedIndex = 1
这将显示 viewController 并且标签已正确初始化。
另一个解决方案是将我用新值设置标签的部分放入 viewWillAppear 或 viewDidLoad。