Wenn die Hauptanwendung auf dem Das iPhone ist nicht aktiv, reply()
ist möglicherweise nicht erreichbar, da die Hintergrundaufgabe vom Betriebssystem zuvor beendet wurde.
Die Lösung besteht darin, eine Hintergrundaufgabe in handleWatchKitExtensionRequest
explizit zu starten, wie in documentation angegeben. Wenn eine Hintergrundaufgabe wie folgt initiiert wird, kann sie bis zu 180 Sekunden lang ausgeführt werden. Dadurch wird sichergestellt, dass die Haupt-App auf dem iPhone nicht gesperrt wird, bevor sie ihre Antwort senden kann.
-Code in der App Delegierter des Haupt-App auf dem iPhone:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
if ([[userInfo objectForKey:@"request"] isEqualToString:@"getData"])
{
// get data
// ...
reply(data);
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
});
}
Falls Sie asynchron benötigen, um Daten zu holen, den folgenden Ansatz verwenden, um sicherzustellen, dass das Verfahren nicht sofort zurückkehren (ohne Aufruf Antwort):
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
NSMutableDictionary *response = [NSMutableDictionary dictionary];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[ClassObject getDataWithBlock:^(BOOL succeeded, NSError *error){
if (succeeded)
{
[response setObject:@"update succeded" forKey:@"updateKey"];
}
else
{
if (error)
{
[response setObject:[NSString stringWithFormat:@"update failed: %@", error.description] forKey:@"updateKey"];
}
else
{
[response setObject:@"update failed with no error" forKey:@"updateKey"];
}
}
reply(response);
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
});
}
Gibt es eine Möglichkeit, es im Simulator zu testen? Da ich keine echte Uhr habe. @vomako –
Der Code sollte auch in einem Simulator funktionieren. – vomako
Q: Warum funktioniert es richtig im Simulator obwohl im Simulator, wenn Watch-App iPhone App im Hintergrund ausgeführt wird. –