2015-01-08 14 views
12

Sto cercando di lanciare il mio iPhone app dal simulatore orologio usando il codice seguente:L'UIApplicationDelegate in iPhone App mai chiamato risposta

WKInterfaceController sottoclasse

[WKInterfaceController openParentApplication:[NSDictionary dictionaryWithObject:@"red" forKey:@"color"] reply:^(NSDictionary *replyInfo, NSError *error) { 
NSLog(@"replyInfo %@",replyInfo); 
NSLog(@"Error: %@",error); 
}]; 

AppDelegate.m

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply 
{ 
NSLog(@"appdelegate handleWatchKitExtensionRequest"); 
NSLog(@"NSDictionary: %@",userInfo); 
NSLog(@"replyInfo: %@",replyInfo); 
} 

L'errore che sto ottenendo è:

Error: Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x7f8603227730 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}

+0

non so WatchKit a tutti, ma l'errore sembra indicare che il codice in 'handleWatchKitExtensionRequest:' deve chiamare il reply block() fornita come argomento a tale metodo. Prova ad aggiungere 'reply (@ {@" data ": @" test data "});' a quel metodo. Questo è solo un banale dizionario come test; Immagino che i documenti di WatchKit ti diranno esattamente quale dovrebbe essere il contenuto di quel dizionario. – pbasdf

+0

Sì, sto ottenendo lo stesso errore quando stampo errore in [InterfaceController openParentApplication: risposta dict:^(NSDictionary * replyInfo, errore NSError *) { NSLog (@ "% @", [replyInfo objectForKey: @ "Key"]) ; NSLog (@ "errore: -% @", [descrizione errore]); suggerire come ottenere i dati nell'app watchkit da questo metodo. Voglio stringa dalla mia app per guardare app kit. grazie in anticipo – jaydev

risposta

18

È necessario chiamare il blocco di risposta, anche se si restituisce nil. Di seguito risolverà il vostro errore:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply 
{ 
NSLog(@"appdelegate handleWatchKitExtensionRequest"); 
NSLog(@"NSDictionary: %@",userInfo); 
NSLog(@"replyInfo: %@",replyInfo); 
reply(nil); 
} 

Vedi the Apple documentation per ulteriori informazioni. Puoi anche restituire un NSDictionary reply(myNSDictionary); con qualunque informazione sarebbe utile tornare alla tua estensione Watchkit, sebbene il dizionario possa contenere solo informazioni che possono essere serializzabili in un file di elenco di proprietà, quindi ad esempio puoi passare le stringhe ma non puoi basta passare un dizionario contenente riferimenti a istanze delle classi personalizzate senza prima impacchettarle come NSData.

+0

Accetto la risposta come l'errore viene rimosso –

+8

Wow, mi ci è voluto per sempre capire che non è possibile passare oggetti personalizzati nel dizionario replyInfo. Anche la conformità a NSCoding non lo fa. E il messaggio di errore che dice che non hai mai chiamato il reply block è fuorviante quando il vero problema è il dizionario replyInfo. – bdmontz

+0

@bdmontz A differenza dei servizi XPC, sembra che non ci siano disposizioni per registrare le classi personalizzate. Peccato! Forse dovresti postarlo come un'altra risposta. – GoodSp33d

14

A parte semplicemente non chiamare il reply block, questo può accadere per almeno un paio di ragioni:

  1. tua applicazione per iPhone è caduto mentre era in corso l'elaborazione della richiesta e, pertanto, non è mai stato in grado di chiamare il reply block. Verifica di non aver inserito accidentalmente nil in NSMutableDictionary, poiché ciò causerebbe un arresto anomalo.
  2. Si sta tentando di inserire qualcosa che non può essere serializzato in un file plist nel dizionario replyInfo (hat tip a @ duncan-babbage). Se è necessario passare un NSAttributedString o il vostro oggetto personalizzato, assicurarsi che sia conforme a NSCoding e fare questo:

Sul lato telefono costruire il dizionario risposta:

NSMutableDictionary *reply = [NSMutableDictionary new]; 
MyCustomObject *myObject = <something you need to send>; 
reply[@"myKey"] = [NSKeyedArchiver archivedDataWithRootObject: myObject]; 
NSAttributedString *myString = <some attributed string>; 
reply[@"otherKey"] = [NSKeyedArchiver archivedDataWithRootObject: myString]; 

e decomprimerlo indietro sulla lato orologio:

NSData *objectData = replyInfo[@"myKey"]; 
MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData]; 
NSData *stringData = replyInfo[@"otherKey"]; 
NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData]; 
+0

Hai dimenticato di dire che per usare l'archiviazione devi conformarti al protocollo '' , che richiede di implementare i suoi metodi richiesti. – EridB

+0

@EridB, non è corretto. Come indicato nella mia risposta, l'oggetto deve essere conforme al protocollo NSCoding per utilizzare l'archiviazione. – bdmontz

+0

@bdmontz grazie per aver risparmiato il mio bacon! Avrei passato la giornata a cercare di capirlo! Ho fatto una bella categoria NSDictionary per nascondere tutto questo cruft anche da me. – eric

6

Vorrei aggiungere che è importante iniziare un'attività in background in handleWatchKitExtensionRequest come specificato nella documentation. Ciò garantisce che l'app principale su iPhone non venga sospesa prima che possa inviare la sua risposta. (L'avvio di un'attività in background non provoca problemi nel simulatore o quando l'app iPhone è attiva. Tuttavia, causa un problema quando l'app iPhone è inattiva.)

Codice nel delegato dell'app dell'app principale su 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]; 
    }); 
} 
Problemi correlati