Как вернуть данные после получения данных от NSURLConnection

У меня есть способ входа в систему. Внутри метода я использую NSURLConnection для входа в систему и хочу получить ответ NSData. Проблема в том, что я возвращаю NSData до того, как соединение действительно получит данные.

- (NSData*)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseData appendData:data]; //responseData is a global variable
NSLog(@"\nData is: %@", [[[NSString alloc] initWithData:responseData     
encoding:NSUTF8StringEncoding]autorelease]);//this works
isLoaded = YES; //isLoaded is a BOOL
}

- (NSData*)login:(NSString*)username withPwd:(NSString*)password{  
isLoaded = NO;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request   
delegate:self];

if(connection){
    NSLog(@"Connected");
}
 while(isLoaded = NO){
[NSThread NSSleepForTimeInterval: 1]; 
}
isLoaded = NO;
return responseData;
}

Программа застревает в цикле while, но без цикла while программа может получать данные с сервера, просто кажется, что метод возвращает responseData до того, как метод делегата изменит их.

Итак, мой вопрос в том, как я могу сделать так, чтобы метод возвращал responseData только после того, как сервер закончит с ним?


person DDFirst Name Dd    schedule 23.05.2012    source источник


Ответы (3)


Если не указано иное, NSURLConnection загружает URL асинхронно. Он использует обратные вызовы deleegate, чтобы информировать делегата о ходе загрузки URL-адреса.

В частности, используйте метод connectionDidFinishLoading: делегата NSURLConnection. Ваш объект NSURLConnection вызовет это после загрузки всех данных. Именно в этом методе вы можете вернуть свои данные.

Вы можете загружать данные синхронно, но это может привести к блокировке пользовательского интерфейса.

Удачи!

person timthetoolman    schedule 23.05.2012
comment
Спасибо за улов. Я обновил свой ответ, но проголосовал за ваш! - person timthetoolman; 24.05.2012

Вам следует провести рефакторинг вашего кода.

Вы используете асинхронный вызов (хорошо), но пытаетесь обработать его синхронно (не очень хорошо - если не используете отдельный поток).

чтобы использовать асинхронное поведение, вам нужен обратный вызов, в стиле какао это обычно метод делегата (или может быть блоком для более нового кода). Собственно это ваш connection:didReceiveData. этот метод будет работать с возвращенными данными, а не с теми, с которых вы начали запрос. поэтому обычно методы, запускающие асинхронный запрос, ничего не возвращают - и уж точно нет, то, что ожидается от запроса.

- (void)login:(NSString*)username withPwd:(NSString*)password
{  
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}


//Note: you cannot change the delegate method signatures, as you did (your's returns an NSData object)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [self.responseData appendData:data]
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{ 
    //Now that the connection was successfully terminated, do the real work.
}

посмотрите на этот пример кода Apple .

person vikingosegundo    schedule 23.05.2012

Вы можете использовать метод запроса синхронизации

- (NSData*)login:(NSString*)username withPwd:(NSString*)password
{  
   NSError *error = nil;
   NSURLResponse *response = nil;

   NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]

   return responseDate;
}

Документация: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/clm/NSURLConnection/sendSynchronousRequest:returnResponse:error:

person Thizzer    schedule 23.05.2012
comment
Разве sendSynchronousRequest не должен быть NSURLrequest? - person DDFirst Name Dd; 24.05.2012
comment
Мое плохое, первым параметром действительно должен быть NSURLRequest, сам метод возвращает объект NSData. - person Thizzer; 24.05.2012