Hi. I have an iOS app with a Watch app that works generally well, but I can't seem to get the Watch app to update with data from the iOS app after it's been suspended/killed by watchOS 4.
The Watch app has complications, which are self-updating (the data is based on dates, so no transfer from iOS - Watch is necessary). The data in the Watch app is richer than that shown in the complications, and includes images etc.
The moment watchOS kills my app when it hasn't been running for a while, it wipes the various bits of data it had in memory, so when I launch the app again, it says there's no data, then spends a few seconds retrieving data from the iOS app, which sometimes works and sometimes doesn't. This looks bad on the Watch, and it's missing any updates the user may have performed in the iOS app.
I should be able to launch the Watch app and see the most up to date information.
I'd like to avoid this situation by using a background task in the Watch app to wake up the iOS app and retrieve data at regular intervals, but all the examples I see use a URLSession within the
scheduleBackgroundRefresh(withPreferredDate:userInfo:scheduledCompletion:)
method. I don't get my data from a server; I get it from the iOS app, and it's all user-created, so there's no server involved anyway.https://developer.apple.com/documentation/watchkit/wkapplicationrefreshbackgroundtask
So, how do I get the Watch app to wake up the iOS app at regular intervals, and retrieve its data so that the Watch app is up to date?
Some code:
In the init() method of the Watch app's ExtensionDelegate.m:
// Schedule a background refresh task
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setHour:1];
NSDate *refreshDate = [[NSCalendar autoupdatingCurrentCalendar] dateByAddingComponents:offsetComponents toDate:[NSDate date] options:0];
[[WKExtension sharedExtension] scheduleBackgroundRefreshWithPreferredDate:refreshDate userInfo:@{} scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
// Successfully scheduled
} else {
NSLog(@"Error scheduling background refresh task for date: %@", refreshDate);
}
}];
This should tell the Watch app to schedule a background refresh task for an hour from now.
The handleBackgroundTasks() method in the Watch app's ExtensionDelegate.m:
- (void)handleBackgroundTasks:(NSSet *)backgroundTasks
{
for(WKRefreshBackgroundTask *currentTask in backgroundTasks) {
NSLog(@"currentTask class = '%@'", [currentTask class]);
NSLog(@"currentTask.userInfo = %@", currentTask.userInfo);
if([[WKExtension sharedExtension] applicationState] == WKApplicationStateBackground) {
if([currentTask isKindOfClass:[WKApplicationRefreshBackgroundTask class]]) {
// Is it here that I get the data from the iOS app? HOW?
// Schedule another background refresh task
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setHour:1];
NSDate *refreshDate = [[NSCalendar autoupdatingCurrentCalendar] dateByAddingComponents:offsetComponents toDate:[NSDate date] options:0];
[[WKExtension sharedExtension] scheduleBackgroundRefreshWithPreferredDate:refreshDate userInfo:@{} scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
// Successfully scheduled
} else {
NSLog(@"Error scheduling background refresh task for date: %@", refreshDate);
}
}];
[currentTask setTaskCompletedWithSnapshot:false];
}
[currentTask setTaskCompletedWithSnapshot:true];
}
}
}
How do I get the data from the iOS app? The iOS app may be (is more often than not) in the background.
Thanks.