2013-10-23 12 views
6

Mam uruchomioną sesję NSURLSession w tle i próbuję znaleźć sposób, aby uzyskać odpowiedź JSON z jednego z callback NSURLDownloadDaskDelegate. Skonfigurowałem swoją sesję, aby akceptować odpowiedzi JSON.NSURLSessionDownloadTaskDelegate Odpowiedź JSON

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

Mogę łatwo analizować odpowiedź JSON dla NSURLSessionDownloadTasks za pomocą następującego wywołania zwrotnego. Zapisuje odpowiedź JSON na piaskownicy w postaci NSURL.

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

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

Mój problem jest jeśli wystąpi błąd wywołania zwrotnego powyżej nie nazywa, wydaje się powoływać jedynie w przypadku pomyślnego pobrania. Ponieważ używam sesji w tle, nie mogę używać żadnych wywołań zwrotnych NSURLSessionDataDelegate. Mogę używać tylko NSURLSessionDownloadTaskDelegate i NSURLSessionTaskDelegate i podczas gdy mogę uzyskać odpowiedź na zadanie za pomocą następującego wywołania zwrotnego. Nie widzę JSON w odpowiedzi.

- (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 ma parametr didReceiveData co daje nam NSData przedmiot, który można użyć, aby uzyskać odpowiedź JSON. Nie widzę, że w callback odbierającego dla NSURLSession z wyjątkiem NSURLDataTask ale nie możemy używać zadań danych w tle, więc w jaki sposób powinniśmy uzyskać odpowiedź JSON? Każda pomoc jest mile widziana

EDIT:

Zwykle ten problem, gdy używam aplikacji w tle (najczęściej, gdy jest on wykluczony pamięć i nie tylko zawieszonej). Zaimplementowałem wywołania zwrotne w appDelegate i jestem w stanie ponownie skojarzyć z sesją.Myślę, żeFinishDownloadingToURL jest wywoływany tylko w przypadku pomyślnego zakończenia zadania, ale gdy zadanie się nie powiedzie, nie ma gwarancji, że zostanie ono wywołane, ale zostanie ono wywołane. z drugiej strony didcompleteWithError jest wywoływany za każdym razem, gdy wystąpi awaria.

+0

Czy możesz wyjaśnić, co masz na myśli przez "jeśli napotkałem błąd". Należy rozróżnić awarie klientów, które nie generują nawet połączenia (na przykład zły adres URL) i odpowiedź serwera, którego kod stanu wskazuje na nieudane żądanie. Tak więc, jeśli oczekujesz kodu statusu 200 (OK) i otrzymasz 500 (Błąd wewnętrznego serwera), jest to błąd drugiej kategorii: połączenie nie zakończyło się niepowodzeniem, ale semantycznie Twoje żądanie się nie powiodło (prawdopodobnie z powodu nieprawidłowo sformułowanego żądania) , powiedzmy źle sformułowany JSON). – CouchDeveloper

+0

Kiedy mówię o błędzie, mam na myśli błędy po stronie serwera, gdzie wraz ze standardowymi kodami odpowiedzi na błędy http oczekuję również ciała JSON –

+0

Powiedzmy, na przykład, jeśli GET zwraca 404 (Nie znaleziono) wraz z odpowiedzią o błędzie w JSON, a następnie 'URLSession: downloadTask: didFinishDownloadingToURL:' nie zostanie wywołany? – CouchDeveloper

Odpowiedz

0

Korzystając z zadania pobierania, można uzyskać dane przy użyciu podanego didFinishDownloadingToURL.

Wszystkie zadania NSURLSession mają również tego delegata. Jeśli tu wejdziesz, a błąd nie będzie zerowy, to wtedy masz błąd. Nie trzeba go wypełniać, aby się tu dostać. Jeśli pojawi się tutaj z błędem, delegat didFinishDownloadingToURL nie zostanie wywołany.

Jeśli nie wystąpi błąd i wszystkie pobrane dane, to zostanie wywołany jeden z nich.

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

EDIT:

Więc coś musi nie postawić konfiguracji prawidłowo, ponieważ nie musi być jakiś sposób, aby uzyskać dane.

Czy wdrażasz application:handleEventsForBackgroundURLSession:completionHandler: w AppDelegate, który spowoduje przywrócenie Twojej aplikacji do obsługi zakończenia, aby uzyskać połączenia delegatów?

Gorąco polecam oglądać sesję WWDC 2013 nr 705, "Whats New in Foundation Networking".Rozmowa w tle rozpoczyna się około 32 minut, a demo kodu zaczyna się od około 37:50

+0

Masz rację, ale moim problemem jest to, że jeśli napotkałem błąd, to didFinishDownloadToURL nie jest wywoływane i dlatego nie mogę odzyskać danych (odpowiedź Json) wysłanych przez mój serwer. Delegat wspólnego zadania didCompleteWithError podał mi obiekt NSError, który nie jest dla mnie użyteczny. Ponieważ didFinishDownloadToURL nigdy nie jest wywoływany, nie mogę przeanalizować odpowiedzi JSON zawierającej błąd wysłany przez serwer. –

+0

W przypadku błędu serwera, nadal powinieneś dostać JSON z powrotem w didFinishDownloadToURL. Tylko błędy klienta (brak internetu itp.) Wywołają błąd didCompleteWithError z błędem. Jeśli otrzymujesz poprawną odpowiedź od serwera (nawet jeśli jest to błąd w JSON), tak jak powiedziałem, powinieneś to odzyskać – RyanG

+0

didFinishDownloadingToURL nie jest wywoływana, jeśli moja aplikacja jest w tle. Widzę tylko wywołanie metody didCompleteWithError. I używam narzędzia do monitorowania ruchu http i widzę odpowiedź JSON wraca, ale w tym momencie nie mam pojęcia, jak uzyskać go w mojej aplikacji. –

Powiązane problemy