Получение данных из блока завершения NSURLResponse

похоже, я еще не полностью понял концепцию блоков...

в моем коде я должен получить данные JSON из asychronous block для возврата из ''. Я погуглил и обнаружил, что если определить variable with __block видимость _mutability_ of эта переменная расширена до block.

но по какой-то причине возвращаемый объект json равен нулю.Интересно, почему?

- (NSMutableDictionary *)executeRequestUrlString:(NSString *)urlString
{
__block NSMutableDictionary *json = nil;
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPShouldHandleCookies:YES];
[request setHTTPMethod:@"GET"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"];

NSString *cookieString = [self.userDefaults objectForKey:SAVED_COOKIE];

[request addValue:cookieString forHTTPHeaderField:@"Cookie"];

[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue currentQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
                       {

                           NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);

                           NSError *error1;
                           NSMutableDictionary * innerJson = [NSJSONSerialization
                                   JSONObjectWithData:data
                                              options:kNilOptions
                                                error:&error1];
                           json = innerJson;

                       }];

    return json;
}

3 ответов


во-первых, чтобы ответить на ваш вопрос:

но по какой-то причине возвращается объект json nil. Интересно, почему?

переменная, которую вы возвращаете, не была установлена в момент ее возврата. Вы не можете собрать результаты сразу после sendAsynchronousRequest:queue:completionHandler: метод вернулся: вызов должен закончить туда и обратно перед вызовом вашего блока и установкой json переменной.

теперь краткое замечание о том, что с этим делать: ваш метод пытается преобразовать асинхронный вызов в синхронный. Постарайтесь сохранить асинхронность, если сможете. Вместо того, чтобы ожидать метод, который возвращает NSMutableDictionary*, сделайте метод, который принимает собственный блок, и передайте словарь этому блоку, когда sendAsynchronousRequest: метод завершается:

- (void)executeRequestUrlString:(NSString *)urlString withBlock:(void (^)(NSDictionary *jsonData))block {
    // Prepare for the call
    ...
    // Make the call
    [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue currentQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);
        NSError *error1;
        NSMutableDictionary * innerJson = [NSJSONSerialization
            JSONObjectWithData:data options:kNilOptions error:&error1
        ];
        block(innerJson); // Call back the block passed into your method
        }];

}

когда вы называете sendAsynchronousRequest:queue:completionHandler:, ты просил асинхронные запрос. Таким образом, он выстраивает запрос и блок в очередь и немедленно возвращается. В какой-то момент в будущем запрос выполняется, а в какой-то момент после этого запускается блок завершения. Но к тому времени ...--1--> уже давно работает.

Если вы хотите иметь возможность синхронно возвращать данные, вы должны сделать синхронный запрос. Это будет висеть этот поток, пока он не завершится, поэтому он не должен быть основным нитка.


Проверьте строку при преобразовании данных, поступающих с сервера, используя код ниже:

 NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);

если строка находится в правильном формате JSON, только тогда ваш объект JSON будет правильным.

надеюсь, это hepls!!