4

I'm trying to request data from the server by using openParentApplication and use it in the watch extension, but I don't get anything back when the main app is not running in the foreground. When the main app is running in the foreground everything works fine.

Mo Al Waili
  • 180
  • 1
  • 9

2 Answers2

10

I had this issue before and the reason was that you haven't registered long running background operation and the system kill it. This is how I sorted this, please see comments for explanations, this is all in AppDelegate file and it in swift but you can easily port it to Objective-c:

private var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

func registerBackgroundTask() {
        backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
            [unowned self] in
            self.endBackgroundTask()
        }
        assert(backgroundTask != UIBackgroundTaskInvalid)
    }

func endBackgroundTask() {
    UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
    backgroundTask = UIBackgroundTaskInvalid
}

// MARK: - Watch Kit
func application(application: UIApplication, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]?, reply: (([NSObject : AnyObject]!) -> Void)!) {

    registerBackgroundTask()

    // Fetch the data from the network here
    // In the competition handler you need to call:
    // the nil can be replaced with something else you want to pass back to the watch kit
    reply(nil)
    if self.backgroundTask != UIBackgroundTaskInvalid {
        self.endBackgroundTask()
    }
}
Greg
  • 25,317
  • 6
  • 53
  • 62
  • Thank you very much the communication works now, but when the app is not running in the foreground I get this error: **the iPhone App never called reply()** – Mo Al Waili Jun 08 '15 at 09:00
  • 1
    @mohammedalwaili make sure you call reply(nil), from your competition handler and also if you have other handler for the failure. You have to call reply(nil) from application handleWatchKitExtensionRequest from every possible scenario: success/ failure. – Greg Jun 08 '15 at 09:05
  • I've tested the app on the simulator and everything works fine, but when testing the app on a real Apple Watch I don't get the data when I kill the app on the iPhone. When the app is not killed on the iPhone I get data back do you have any idea why? – Mo Al Waili Jun 08 '15 at 12:22
  • @mohammedalwaili it work for me. try do some debugging to narrow down the area where the issue could appear. I'm using this code in the real app and it's all good. – Greg Jun 08 '15 at 12:57
  • iOS really doesn't launch a terminated application in the background at the right time after a call to openParentApplication. See my question & answer about the topic. – Cihan Tek Jul 08 '15 at 06:17
2

Just adding some Obj-c equivalent that does this, although mine is using straight GCD so it is a slightly different approach.

 __block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid;
dispatch_block_t endBlock = ^ {
    if (identifier != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:identifier];
    }
    identifier = UIBackgroundTaskInvalid;
};
identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock];

reply = ^(NSDictionary *replyInfo) {
    reply(replyInfo);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
        endBlock();
    });
};
Brian Trzupek
  • 4,982
  • 1
  • 16
  • 19