Parse Push Notification Payload nil in didFinishLaunchingWithOptions - ios

Parameters: iOS 9.1, iphone 5S, xcode 7.1, Swift 2, Parse SDK 1.9.0
I am trying to capture push notification messages sent via Parse for all states of the receiving device (i.e. foreground/background/not loaded/device turned off). For all cases, my device receives the push notifications but in some cases the payload/userInfo dictionary does not arrive.
For situations where:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
is called (e.g. app in foreground) in the AppDelegate, the userInfo dictionary is received correctly and I can save the message, issue a notification & display it in an appropriate ViewController.
However, where
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
is called in the AppDelegate (e.g. if device is turned off and the push notification banner is "swiped" to open the App), the payload obtained from the statement:
if let notificationPayload:NSDictionary = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary
is always nil and I cannot complete the same actions as above.
The statements that generate the push are:
push.setData(["alert" : message, "badge": "Increment", "content-available": NSNumber(integer: 1)])
push.sendPushInBackground()
where message is a String containing the message to be displayed.
I have read numerous posts on SO, etc. & tried various ways to solve this but cannot find a solution. Any ideas/assistance would be greatly appreciated. I can post more code if necessary but I am basically following the standard approach from Parse examples & other SO posts.
RB

Related

App crashing [FIRApp appWasConfiguredTwice:usingOptions:]

iOS Extension - Fatal Exception: com.firebase.core Default app has already been configured.
enter image description here
From the message it is clear that FIRApp's configure function is called twice by your app. It is supposed to call once. The best place to call it, is in the func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool in your AppDelegate.
In order to identify from where it is being called you can use 2 approaches.
Press CMD + Shift + F and search for configure keyword and identify from the results.
Add a symbolic break point and app will pause when configure function get called. See the screenshots below:

BGAppRefreshTask in the BackgroundTasks

I have this code that show a message "Msg Background" when the application is in Background. What I need is that as long as the application continues in the background show that message every 2 minutes (just an example of time). So far the code I have shows the message only once, apparently this sentence is not working properly.
UIApplication.shared.setMinimumBackgroundFetchInterval (UIApplication.backgroundFetchIntervalMinimum)
I also have this warning: 'setMinimumBackgroundFetchInterval' was deprecated in iOS 13.0: Use a BGAppRefreshTask in the BackgroundTasks framework instead
I am using swift 5 and Xcode 11
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
GMSServices.provideAPIKey("AIzaSyBSpAt5zqvbh73FmG_Kb6xpiFMkWRmHppg")
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
return true
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("Msg Background")
}
}
As Paulw11 said, it's not called in fixed interval. The OS controls when it is going to be executed. We cannot expect the specific time because of it.
You probably know this, but I'm going to add this bit just in case, setMinimumBackgroundFetchInterval has deprecated on iOS 13 and later. You might want to consider to use BackgroundTasks Framework instead.
but if you want to test performFetchWithCompletionHandler, you can use XCode Navigation Bar > Debug > perform Background Fetch.
screenshot of XCode navigation bar to find option
I hope it can help!

Swift - didReceiveRemoteNotification - PromiseKit

Can I use PromiseKit in AppDelegate - application:didReceiveRemoteNotification method?
I am using GCM to push notification from the server. Once the app receives the notification I would like to fetch some data from the server, parse it, massage it and then save it using Core Data.
Am using PromiseKit to chain the steps together and its working fine when you manually refresh the data with a swipe down on TableViewController. However, when I use the same logic to refresh data on push notification from the sever, the behaviour is unpredictable, sometimes the execution stops at firstly(), other times it executes couple of then blocks and then nothing.
Basically this is what I would do:
func application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
firstly() {
// fetch data (JSON) from server
}.then {
// Parse the JSON
}.then {
// Sync the db (using Core Data)
}.then {
// Raise local Notification
}.error {
}
}
Obviously, looks like the control exists the didReceiveRemoteNotification method before all the Promises are fulfilled.
PromiseKit gurus, any suggestions? The only thing I can think of is to rewrite the code without PromiseKit for sequential operation.
PromiseKit is an asynch library.
All your then blocks are executed asynchronously. The method didReceiveRemoteNotification will return before your then blocks are called.
If you want to make a synch call, you should not use promisekit!

Pushes open tracking with Parse

I have implemented the push open tracking like described here https://parse.com/docs/ios/guide#push-notifications-tracking-pushes-and-app-opens.
If i open the push on the device, in the parse dashboard, the push opens number is updated on the previous push sent.
For example, if i send the push "Hello" twice and open it twice on the device, the push opens will be 1 for the first push, 0 for the last one.
I can reproduce it if the app is in background or if it's closed.
I use the latest pod Parse (1.11.0) and the application is in Swift.
The source code :
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
if application.applicationState == .Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
}
I tried with the following code to check if the BFTask is completed. Everything is fine and the task has the completed status.
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo).continueWithBlock({ (task) -> AnyObject! in
assert(task.completed, "task should have completed")
assert(!task.cancelled, "task should not have been cancelled")
assert(!task.faulted, "task should not complete due to error or exception")
return task
})
Did someone experience the same issue ?

WKInterfaceController.openParentApplication is delayed on real device?

I've been tracking this bug for days and finally realized the issue is that there is an actual delay with WKInterfaceController.openParentApplication. I am not referring to the callback in the Apple Watch, but the AppDelegate event in the iPhone.
Here's what I'm doing in the Apple Watch:
override func awakeWithContext(context: AnyObject?) {
var userInfo = [
"test": 123
]
WKInterfaceController.openParentApplication(userInfo, reply: nil)
}
Then in the iPhone, I'm doing this in AppDelegate:
func application(application: UIApplication, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]?, reply: (([NSObject : AnyObject]!) -> Void)!) {
let test = userInfo["test"]
// Do something
}
The problem is when I call WKInterfaceController.openParentApplication, there is a 2 or 3 second delay before the handleWatchKitExtensionRequest event is triggered in the iPhone. This is problematic if the user performs an action on their watch really quickly and puts down their arm right after. I can't assume the user is going to hold up their arm for 3 seconds until the watch sends the command.
Here's the catch: if the user wakes up the watch, the command still doesn't get sent to the iPhone.. UNTIL the user opens up the original app that sent the WKInterfaceController.openParentApplication. I don't think any of this would be a problem without this catch, the command should be queued until the watch is awakened, not awakened AND reopen the app.
Any workaround that can be done for this? I plan on logging this as a bug, but wanted to see if anyone has any thoughts or experience with this?

Resources