2010-02-12 69 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 2010-02-12 09:48:16

+0

如果您想阻止UI,只需在啓動請求時顯示'UIAlerView'並在'connectionDidFinishLoading'中將其解除。 – FelixLam 2010-02-12 09:58:57

0

我使用NSNotification或那個位置。在DidFinishLoading方法發佈的通知,

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

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

處理在anyclass該通知並執行

-(void)handleMethod:(NSNotification *)ntf