I am working on core data and silent notifications. I don't have any thread safe implementation in core data. And when i get silent notifications i need to fetch & save couple of items into database.
So my question is does didReceiveRemoteNotification:fetchCompletionHandler always works on main thread? (Even the app is on background).
I did the experimentation, i sent silent notification when app is on the background, didReceiveRemoteNotification triggered in Thread 1(UIThread).
But still i want to make sure and prevent crashes related with thread issues.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0)
{
}
Related
I have implemented Push Notification in my iOS app.I can see two delegate methods for didReceiveRemoteNotification like the below methods: What is the difference between these two methods?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { }
and
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
}
The first one is deprecated in iOS 10.0 use the second one. Information for second one
This method will be invoked even if the application was launched or resumed because of the remote notification. The respective delegate methods will be invoked first. Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented.
And for first one
Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:] for user visible notifications and -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] for silent remote notifications
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { }**
Called when your app has received a remote notification. This method is deprecated in iOS 10.0
For more details click here
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { completionHandler(UIBackgroundFetchResultNewData); }**
Tells the app that a remote notification arrived that indicates there is data to be fetched.
For more details click here
The below method is updated one
This delegate method offers an opportunity for applications with the "remote-notification" background mode to fetch appropriate new data in response to an incoming remote notification. You should call the fetchCompletionHandler as soon as you're finished performing that operation, so the system can accurately estimate its power and data cost.
This method will be invoked even if the application was launched or resumed because of the remote notification. The respective delegate methods will be invoked first. Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
}
You app needs to handle all the possible push notification delivery states:
Your app was just launched
Your app was just brought from background to foreground
Your app was already running in the foreground
You can tell whether your app was just brought to the foreground or not in didReceiveRemoteNotification using this bit of code: Deprecated in iOS 10.0
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo;
Tells the app that a remote notification arrived that indicates there is data to be fetched. Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
In addition
The block to execute when the download operation is complete. When calling this block, pass in the fetch result value that best describes the results of your download operation. You must call this handler and should do so as soon as possible. For a list of possible values, see the UIBackgroundFetchResult type.
This method is called when a push notification is received while the app is in background mode and the user clicks on notification. But I want to call a method when notification comes in background mode without the user to click on the notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"%#",userInfo);
}
For this to happen you need to enable Background mode for remote notifications. You can find it Capabilities section of the project. Besides that your incoming Notification Payload should contain content-available:1 key-value pair.
Then this method will be called immediately without user interaction.
Note: This works if the app is in Background or suspended state. If the app is completely killed or force quit by the user, it will not work.
I am facing a problem with Push notification, and the problem occurs only on clients Enterprise environment.
The problem is as follows: when I am testing on my side (development and not distribution) I receive notification and - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo is called every time and works perfectly through the following cases:
When app is not opened (not in memory or suspended apps), and not in background nor foreground
When app is opened but in background.
When app is in foreground.
But when the client tries it on his environment (after mdm wrapping), the following happens in each case:
Case 1: Works successfully, and didReceiveRemoteNotification method gets called fine.
Case 2: Receives notification, but didReceiveRemoteNotification is not called.
Case 3: I don't see any notification neither in notification centre and didReceiveRemoteNotification is not called also.
I searched for anything that could help, and I only found that there is this - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler maybe be a better replacement.
Any other suggestions? Any thing to check or to consider? Is it maybe an iOS related issue? Caused by MDM configuration (a long shot I know)?.
Thanks in advance.
I found the solution, I used this method - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler which suited well.
In an iOS app using remote notifications (coming from Parse.com) I have arrived, after spending some time researching on the subject, to the conclusion that I should not use remote notifications in the background or possibly use silent notifications.
But silent notification seem quite complex.
For example:
In this code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"application:didReceiveRemoteNotification:fetchCompletionHandler:");
completionHandler(UIBackgroundFetchResultNewData);
}
The fact of adding the last line (completionHandler) prevents an error message.
But what does this do exactly? Where does this completionHandler come from?
I have never touched silent-notifications and I am kind of lost there.
The last line is completing block that will be called when you application is in background.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
Above method get called when your application in running in background OR foreground mode.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
If you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives.
When a remote notification arrives, the system displays the notification to the user and launches the app in the background (if needed) so that it can call this method. Launching your app in the background gives you time to process the notification and download any data associated with it, minimizing the amount of time that elapses between the arrival of the notification and displaying that data to the user.
Let me know if you need anymore clarification.
There's a new feature in iOS 8: using a push notification to wake an app, which also lets the app refresh data in the background. How do I use this feature?
The push notification arrives with a value of 1 for the key 'content-available'. However, no data is received if the app is not already running in background. Why not?
There are couple of things here,
1.U need to check Remote Notification on under Background mode of the target in Capabilities section.
2.U need to implement below method,
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler