UIApplication.registerForRemoteNotifications() must be called from main thread only
Solution 1
In swift4
You can solve this issue with
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
Hope this will help...
Solution 2
For Objective C, the below code works
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
Solution 3
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:
- New in Xcode 9 – Main Thread Checker.
- **Enable detection of UI API
misuse from background thread**
- Detects AppKit, UIKit, and WebKit method calls that are not made on the main thread.
- Automatically enabled during debugging, and can be disabled in the Diagnostic tab of the scheme editor.
- Main Thread Checker works with Swift and C languages.
Solution 4
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
}
}
Solution 5
In swift 4 or 5
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
on Objectiv-C
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
Related videos on Youtube
![Krunal](https://i.stack.imgur.com/mme83.jpg?s=256&g=1)
Krunal
Contact me, if you're looking for a CTO or Engineering Director/VP. contact: +91 - 9737007007 mail: [email protected] Following some great SO users....
Updated on April 10, 2021Comments
-
Krunal about 3 years
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?
-
Duyen-Hoa about 7 yearsAs said in the error message, you have to wrap the call to
UIApplication.shared.registerForRemoteNotifications()
in the main thread. :) Let google how to call it in main thread ... -
mfaani about 7 years@Hoa why would you need to do this from mainThread? It's not UI related...or is it because it has the potential to happen a few seconds later and that could cause unexpected behavior?
-
Krunal about 7 yearsI also have same confusion, why Swift 4 is showing me this error indicator...
-
mfaani about 7 years@Sulthan The
UIApplication.shared.registerForRemoteNotifications()
isn't UI related (you don't prompt users when you get token for silent Notifications). So the line the error is showing is confusing. However registering for the badges, alerts, sounds is UI related and it's much better to do it from main thread...so overall the entire block ofcenter.requestAuthorization(options:...
must be done from main thread...it makes sense -
joshLor about 7 yearsI had a problem that extends this that can be found here. I had the error message addressed in this question as well as others.
-
-
mfaani about 7 yearsCurious how did you learn this Xcode 9 new settings so quick? There are no WWDC videos out yet!
-
Sulthan about 7 years@Honey The release notes usually contain all the necessary changes :)
-
vadian about 7 years@Honey Some people read the release notes and the documentation ;-)
-
mfaani about 7 years@vadian facepalm...I'm still a noob...this is actually the first time I able to catchup and follow up on a WWDC
-
vadian about 7 years@Honey Seriously, it's always worth it to read the (Xcode) release notes.
-
cvb about 7 yearsThis thing is tripping on UIKit tasks done in a background context, which has nothing to do with the UI. Don't down vote this....it's good info.
-
mfaani about 7 years@BadhanGanesh (I didn't downvote nor upvoted) if that's not what you intended then rewrite it...because it's like someone saying I have problem X...and then you replying you can do Y....well the OP is looking for answers. If it's just an explanation than make it clear that it's not answer
-
nathan almost 7 yearsEven simpler, there's no need for the closure:
DispatchQueue.main.async(execute: UIApplication.shared.registerForRemoteNotifications())
-
Philip De Vries almost 7 yearsHmmmm so even traversing through the subviews is giving me this warning. I'm not trying to manipulate anything in the UI, just creating thumbs in the background. Should I really dispatch every line dealing with UIViews to the main thread?
-
badhanganesh almost 7 years@PhilipDeVries All UIKit method-calls should be in main thread. You are probably calling methods of UIKit in BG.
-
bvpb almost 7 years@nathan I think you need the closure. I got a
Cannot invoke 'async' with an argument list of type '(execute: Void)'
error using your example. -
nathan almost 7 yearsSorry, typo:
DispatchQueue.main.async(execute: UIApplication.shared.registerForRemoteNotifications)
.execute
expects a function/closure of type() -> Void
soregisterForRemoteNotifications
works -
Pooja Srivastava over 6 yearshow to write in objective c.
-
Ming Zhu over 6 yearsWill this kind of warning/error be subject to AppStore rejection? I asked this because I have a really special usage of WKWebView in a background thread (acting as a Javascript engine, instead of JSCore, since the WebView has better JS performance with JIT compilation and JS execution)
-
badhanganesh over 6 years@PoojaSrivastava
dispatch_async(dispatch_get_main_queue(), ^{ //Do stuff });
-
cristallo over 6 yearsI am pretty confused, even if I am using the DispatchQueue.main.async, the Main Thread Checker is still displaying the warning