Reputation: 79766
Xcode 9 (iOS 11) showing me an error/warning while registering for Push (remote) notification.
Here is error message
And here is code, I've tried:
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
}
}
Error/Warning Line:
UIApplication.shared.registerForRemoteNotifications()
How to resolve this?
Upvotes: 86
Views: 46766
Reputation: 3464
TL;DR:
All UI manipulations should be done in the Main Thread to avoid problems. If failed to do so, Main Thread Checker (Newly introduced debugging feature in Xcode 9) will produce issues at Runtime. So wrap your code in Main Thread block like below to avoid glitches and runtime warnings.
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
In Xcode releases before ver. 9, the warnings related to main thread would get printed in the console area textually. Anyway, you can optionally disable (not a recommended approach) the Main Thread Checker in the Diagnostic settings in Edit Scheme.
Explanation:
Apple introduced a new debugging option in Xcode 9 for checking issues at Runtime for UIKit and other API's that manipulate UI elements. If there's any change to the UI elements from UIKit API at Runtime, without a Main thread block, it is highly likely to cause UI glitches and crashes. The Main Thread Checker is enabled by default to catch those issues at runtime. You can disable Main Thread Checker in the Edit Scheme window just like below, although it is not really recommended to do so:
If you have any older SDK's or Frameworks, when updating to Xcode 9, you may face this warning since some of the UIKit method calls wouldn't have been wrapped in Main Thread. Updating them to latest version would fix the issue (if the developer is aware of it and fixed it).
Quote from Xcode 9 beta release notes:
Upvotes: 39
Reputation: 703
In swift 4 or 5
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
on Objectiv-C
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
Upvotes: 6
Reputation: 6067
In swift4
You can solve this issue with
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
Hope this will help...
Upvotes: 153
Reputation: 1115
This is what worked for me. Courtesy of @Mason11987 in the accepted comment above.
DispatchQueue.main.async() { code }
Upvotes: 1
Reputation: 1358
Hope this will help
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
Upvotes: 1
Reputation: 7459
This is also correct way to do in Swift 4.0
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge], completionHandler: {(granted,error) in
if granted{
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
})
Upvotes: 3
Reputation: 2209
For Objective C, the below code works
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
Upvotes: 51
Reputation: 285220
The error message is pretty clear: dispatch registerForRemoteNotifications
to the main thread.
I would use the granted
parameter and handle the error
accordingly
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print(error!)
// handle the error
}
}
Upvotes: 6