2010-02-12 3 views
2

비동기 모드에서 NSURLConnection을 사용하고 완료를 기다리고 있습니다. 대기 중에 NSRUNLOOP을 사용하여 이벤트를 처리합니다. 대부분의 경우 (3G 및 WIFI) 에서 작동하지만 GSM DATA 및 EDGE 환경에서는 응용 프로그램이 임의로 끊깁니다.IPHONE SDK : NSURLConnection 비동기/대기 완료 버그?

내 코드 :

(void) connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
_requestCompleted = TRUE; 
CFRunLoopStop(CFRunLoopGetCurrent()); 
} 

(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 

_response = (NSHTTPURLResponse *)response; 

[ _response retain]; 

} 
(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
/* Append the new data to the received data. */ 
[_receivedData appendData:data]; 
} 


(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
_requestError = error; 
NSLog(@"request error - cause : %@", [_requestError localizedDescription ]); 
_requestCompleted = TRUE; 
[_requestError retain]; 
CFRunLoopStop(CFRunLoopGetCurrent()); 
} 

(NSString*)downloadFileFromURL:(NSString*)url 
{ 
NSURLRequest *request = nil; 

NSString *contents = nil; 
NSData *response = nil; 
int tries; 
NSURLConnection *URLConnection = nil; 
int i = 0; 
NSDate* dateLimit; 

[_mutex lock]; 
NSLog(@"url = %@", url); 
NSString *requestWithEscaping = [ url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; 


request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestWithEscaping] 
         cachePolicy: NSURLRequestReloadIgnoringLocalCacheData 
         timeoutInterval:30]; 


for (tries = 0; tries < HTTP_REQUESTS_TRIES && response == nil ; tries ++) { 
    [_receivedData setLength:0]; 
    _requestCompleted = FALSE; 
    _requestError = nil; 
    _requestTimeout = FALSE; 

    if (URLConnection == nil) 
     URLConnection = [ NSURLConnection connectionWithRequest:request delegate:self]; 
    else { 
     [URLConnection cancel ]; 
     [URLConnection start]; 
    } 

    if (URLConnection == nil) { 
     NSLog(@"No connection ! maybe mistake in Request Format ?"); 
     continue; 
    } 

    for (i = 0; ; i++) { 
     dateLimit = [[NSDate date] addTimeInterval:INTERVALL_LOOP]; 

     [ [NSRunLoop currentRunLoop] runUntilDate:dateLimit]; 

     if (_requestCompleted == TRUE) 
      break; 

     if (i > (int)(HTTP_TIMEOUT_FIRE * (1/INTERVALL_LOOP))) { 
      _requestTimeout = TRUE; 
      break; 
     } 
    } 

    if (_requestTimeout) { 
     [ URLConnection cancel]; 
     NSLog(@"request timeout"); 
     continue; 
    } 
    if (_requestError) { 
     NSLog(@"request error"); 
     continue; 
    } 

    NSLog(@"Request success"); 
    break; 
} 

if (_requestTimeout) { 
    _lastErrorType = ServicesRequestManager_error_Network; 
    [ _lastErrorString setString:@"Délai de connexion depassé"]; 
    [ _mutex unlock]; 
    return nil; 
} 

if (_requestError) { 
    NSLog(@"ERROR Cannot get %@ - cause : %@",url, [ _requestError localizedDescription ]); 
    _lastErrorType = ServicesRequestManager_error_Network; 
    [_lastErrorString setString:@"Impossible de se connecter" ]; 
    [ _mutex unlock]; 
    return nil; 
} 

if ([ _response statusCode] != 200) { 
    NSLog(@"ERROR Download file %@ HTTP response - code : %d", url, [ _response statusCode]); 
    [_lastErrorString setString:[ NSString stringWithFormat:@"Error http code : %d", [_response statusCode]]]; 
    _lastErrorType = ServicesRequestManager_error_Service; 
    [_lastErrorString setString:@"Le service n'est pas disponible actuellement" ]; 
    [ _mutex unlock]; 
    return nil; 
} 

contents = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding]; 
[ _mutex unlock]; 
return contents; 

}

답변

3

있는 NSURLConnection은 이미 비동기입니다. 대리자 메서드를 구현하기 만하면됩니다. MainThread (예 : 진행률 표시 줄)에서 UI를 업데이트하려면 didReceiveData에서 수정할 수 있습니다.

+0

확인을 구현하지만 난 완료를 기다려야합니다. 시간 초과도 처리해야합니다. – mneveren

+0

UI를 차단하려면 요청을 시작할 때'UIAlerView'를 표시하고'connectionDidFinishLoading'에서이를 닫으십시오. – FelixLam

0

나는 NSNotification 또는 그 puspose를 사용합니다. DidFinishLoading 방법에서,

[[NSNotificationCenter defaultCenter] postNotificationName:@"Name" object:someObject]; 

을 알림을 게시하고

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMethod:) notificationName:@"Name" object:nil]; 

에 의해 anyclass에서이 통지를 처리하고

-(void)handleMethod:(NSNotification *)ntf