2013-10-23 13 views
6

Sto eseguendo una sessione NSURLSession in background e sto cercando di trovare un modo per ottenere la risposta JSON da uno dei callback NSURLDownloadTaskDelegate. Ho configurato la mia sessione per accettare le risposte JSON.NSURLSessionDownloadTaskDelegate Risposta JSON

NSURLSessionConfiguration *backgroundSession = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.Att.Locker.BackgroundUpload"]; 
backgroundSession.HTTPAdditionalHeaders = @{ @"Accept":@"application/json"}; 
session = [NSURLSession sessionWithConfiguration:backgroundSession delegate:uploader delegateQueue:nil]; 

posso facilmente analizzare la risposta JSON per NSURLSessionDownloadTasks utilizzando la seguente callback. Scrive la risposta JSON sulla sandbox sotto forma di NSURL.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { 

    //Reading the Json response from the sandbox using the NSURL parameter 
} 

Il mio problema è che se ho incontrato un errore il callback di cui sopra non si chiama, sembra avere invocato solo in caso di un download di successo. Dal momento che sto usando una sessione in background non posso usare nessuno dei callback NSURLSessionDataDelegate. Posso solo utilizzare NSURLSessionDownloadTaskDelegate e NSURLSessionTaskDelegate e mentre posso ottenere la risposta dell'attività utilizzando il seguente callback. Non vedo il JSON nella risposta.

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { 


NSHTTPURLResponse *response = (NSHTTPURLResponse *)downloadTask.response; 
NSDictionary *httpResponse = [response allHeaderFields]; 

NSLog(@"Response Header Fields:%@",[httpResponse allKeys]); 
} 

NSURLConnection ha un parametro didReceiveData che ci dà un oggetto NSData che possiamo utilizzare per ottenere la risposta JSON. Non vedo che nelle callback delegato per NSURLSession tranne NSURLDataTask ma non possiamo usare i compiti dati in background in modo da come facciamo a ottenere la risposta JSON fuori? Ogni aiuto è apprezzato

EDIT:

Io di solito si riscontra questo problema, mentre sto facendo funzionare l'applicazione in background (soprattutto quando è calciato fuori la memoria e non solo sospeso). Ho implementato i callback nell'appDelegate e sono in grado di associarmi alla sessione.Penso che didFinishDownloadingToURL sia invocato solo in caso di completamento con successo di un'attività, ma quando un task fallisce non c'è la garanzia che verrà chiamata ma d'altra parte doneCompleteWithError viene chiamato ogni volta che si verifica un errore

+0

Potrebbe chiarire cosa intendi con "se riscontro un errore". È necessario distinguere tra errori del client che non generano nemmeno una connessione (ad esempio, URL errato) e una risposta del server il cui codice di stato indica una richiesta non riuscita. Quindi, se si prevede un codice di stato 200 (OK) e si ottiene invece un errore 500 (Internal Server Error), si tratta di un errore della seconda categoria: la connessione non ha avuto esito negativo, ma semanticamente la richiesta non è riuscita (probabilmente a causa di un corpo di richiesta non valido , dire JSON malformato). – CouchDeveloper

+0

Quando dico un errore intendo errori lato server dove insieme con i codici di risposta errore standard standard sto anche aspettando un corpo JSON –

+0

Dire, per esempio se un GET restituisce 404 (non trovato) insieme a una risposta di errore in JSON, quindi 'URLSession: downloadTask: didFinishDownloadingToURL:' non sarà chiamato? – CouchDeveloper

risposta

0

Utilizzando un'attività di download, è possibile ottenere i dati utilizzando lo didFinishDownloadingToURL come indicato.

Tutte le attività NSURLSession hanno anche questo delegato. Se entri qui e l'errore non è zero, allora hai un errore. Non è necessario completare per entrare qui. Se arriva qui con un errore, il delegato didFinishDownloadingToURL non verrà chiamato.

Se non vi sono errori e tutti i dati vengono scaricati, verranno richiamati entrambi i delegati.

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 
{ 
    NSLog(@"didCompleteWithError"); 
} 

EDIT:

Quindi, qualcosa deve scommettere non configurato correttamente come ci deve essere un modo per ottenere i dati.

Stai implementando application:handleEventsForBackgroundURLSession:completionHandler: nel tuo AppDelegate che collegherà la tua app al gestore di completamento per ottenere le chiamate del delegato?

Consiglio vivamente di guardare la sessione WWDC 2013 n. 705, "Whats New in Foundation Networking".La sessione di discussione in background inizia intorno ai 32 minuti e la demo del codice inizia intorno al 37:50

+0

Hai ragione ma il mio problema è che se riscontro un errore, allora FinsoleDownloadToURL non viene chiamato e quindi non riesco a recuperare i dati (risposta Json) inviati dal mio server. Il delegato dell'attività comune didCompleteWithError mi fornisce solo un oggetto NSError che non mi è utile. Poiché didFinishDownloadToURL non viene mai chiamato non riesco ad analizzare la risposta JSON contenente l'errore inviato dal server –

+0

In caso di un errore del server, dovresti comunque riavviare JSON all'interno didFinishDownloadingToURL. Solo errori del client (senza Internet, ecc.) Attiveranno l'errore didCompleteWithError con un errore en. Se ricevi una risposta valida dal server (anche se si tratta di un errore in JSON), come ho detto che dovresti ancora recuperarlo – RyanG

+0

didFinishDownloadingToURL non viene richiamato se la mia app è in background. Vedo solo doneCompleteWithError chiamato. E sto usando uno strumento per monitorare il traffico http e vedo la risposta JSON tornare ma a questo punto non ho idea di come ottenerlo nella mia app. –