2015-05-02 3 views
14

Sachverhalt: Ich benutze openParentApplication in der Watch-App, um handleWatchKitExtensionRequest in der Haupt-App aufzurufen. Dies funktioniert gut im Simulator und funktioniert auch auf den tatsächlichen Geräten (Apple Watch und iPhone), wenn die iPhone App aktiv/offen ist.Wie verwende ich korrekt "openParentApplication" und "handleWatchKitExtensionRequest", so dass "reply()" aufgerufen wird?

Problem: Wenn ich es auf die tatsächlichen Geräte (Apple Watch und iPhone) laufen, handleWatchKitExtensionRequest keine Daten an openParentApplication zurückkehrt, wenn die Haupt iPhone App nicht aktiv/offen ist.

-Code in InterfaceController.m in der WatchKit Erweiterung:

NSDictionary *requst = @{ @"request" : @"getData" }; 
[InterfaceController openParentApplication:requst 
            reply:^(NSDictionary *replyInfo, NSError *error) { 
             // do something with the returned info 
            }]; 

-Code in der App Delegierter des Haupt-App auf dem iPhone:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply 
{ 
    if ([[userInfo objectForKey:@"request"] isEqualToString:@"getData"]) 
    { 
    // get data 
    // ... 
    reply(data); 
    } 
} 

Antwort

16

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]; 
    }); 
} 
+0

Gibt es eine Möglichkeit, es im Simulator zu testen? Da ich keine echte Uhr habe. @vomako –

+0

Der Code sollte auch in einem Simulator funktionieren. – vomako

+0

Q: Warum funktioniert es richtig im Simulator obwohl im Simulator, wenn Watch-App iPhone App im Hintergrund ausgeführt wird. –

Verwandte Themen