2013-08-27 8 views
1

Я пытаюсь заполнить UITableView, извлекая URL-адрес. Чтобы избежать зависания UI, я использую dispatch_async(dispatch_queue_t queue, ^(void)block), производя асинхронный выборки. В асинхронном блоке с использованием NSRunLoop для ожидания ответа.Как ждать асинхронного ответа NSURLConnection

Вот мой код выборка:

- (BOOL)isFinished { 
    return _finished; 
} 

- (void)startReceive { 
    NSURLRequest* request = [NSURLRequest requestWithURL:self.baseURL]; 
    self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; 
    assert(self.connection); 
} 

- (void)stopReceiveWithStatus:(NSString*)statusCode { 
    if (self.connection) { 
     [self.connection cancel]; 
     self.connection = nil; 
    } 
    self.finished = YES; 
    NSLog(@"Stop Receive with status code %@", statusCode); 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    assert(connection == self.connection); 
    NSHTTPURLResponse* httpResponse = nil; 
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 
     httpResponse = (NSHTTPURLResponse*) response; 

     if (httpResponse.statusCode != 409) { 
      // I need 409 to fetch some data 
      [self stopReceiveWithStatus:[NSString stringWithFormat:@"HTTP error %2d", httpResponse.statusCode]]; 
     } 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    assert(connection == self.connection); 
    self.sessionID = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    assert(connection == self.connection); 

    [self stopReceiveWithStatus:@"Connection failed"]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    assert(connection == self.connection); 

    [self stopReceiveWithStatus:nil]; 
} 

UITableViewController:

// refreshControl handler 
- (IBAction)refresh { 
    [self startRefreshingAnimation]; 
    dispatch_queue_t loaderQ = dispatch_queue_create("loading transmission data", NULL); 
    dispatch_async(loaderQ, ^{ 
     [self foo]; 
     while(!self.t.finished) { 
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
     } 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self endRefreshingAnimation]; // end 
     }); 
    }); 
} 

- (void)foo { 
    NSLog(@"session id: %@", self.t.sessionID); 
} 

sessionID Это будет заполнен, когда запрос HTTP сделал. Теперь проблема в том, что я не могу получить sessionID при первом вызове, потому что в первый раз он не будет заполнен, а во второй раз он работает хорошо. Как я могу получить его при первом звонке?

Я новичок в iOS. Если у вас есть лучшее решение для решения этой проблемы, пожалуйста, скажите мне, спасибо.

+0

В конце концов, я положил 'NSRunLoop' в SESSIONID добытчика чтобы убедиться, что sessionID заполнен – Pikaurd

ответ

0

Существует хорошая структура, не тратьте ваше время.

https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking

Upd. Вы можете сделать свой запрос как:

NSURL *url = self.baseURL; 
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
        height, @"user[height]", 
        weight, @"user[weight]", 
        nil]; 
[httpClient postPath:@"/myobject" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { 
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; 
NSLog(@"Request Successful, response '%@'", responseStr); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
NSLog(@"[HTTPClient Error]: %@", error.localizedDescription); 
}]; 
0

Вы должны использовать сторонние библиотеки для обработки сетевых соединений, таких как STHTTPRequest:

STHTTPRequest *r = [STHTTPRequest requestWithURLString:@"http://www.apple.com"]; 

r.completionBlock = ^(NSDictionary *headers, NSString *body) { 
    // ... 
}; 

r.errorBlock = ^(NSError *error) { 
    // ... 
}; 

[r startAsynchronous];