NSURLConnection и центральная отправка

Целесообразно ли обернуть NSUrlConnection в блоках стиля gcd и запустить его в очереди low_priority?

Мне нужно убедиться, что мои соединения не происходят в основном streamе, а соединения должны быть асинхронными. Мне также нужно несколько одновременных запросов сразу.

Если я иду по маршруту gcd, я не уверен, в какой stream запускаются методы NSUrlConnectionDelegate.

NSURLConnection полагается на делегатов, поэтому, как только соединение будет завершено, любой class-shell, который обрабатывает его, должен будет вызвать своего вызывающего. Я не уверен, как бороться со всеми различными обратными вызовами, которые вызывают при запуске / завершении работы соединения:

- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)response; - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData; - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; - (void)connectionDidFinishLoading:(NSURLConnection *)connection; 

Должен ли я просто вызвать синхронные версии, но обернутые в блоки gcd? И если я хочу отменить вызов, используйте ‘dispatch_suspend’?

 dispatch_async(queue,^{ NSString* result = [self mySynchronousHttp:someURLToInvoke]; }); // If I need to cancel dispatch_suspend(queue); 

Я рекомендую вам видеть сессии WWDC о сетевом приложении в iPhone OS.

  • WWDC 2010 Сессия 207 – Сетевые приложения для iPhone OS, часть 1
  • WWDC 2010 Session 208 – Сетевые приложения для iPhone OS, часть 2

Лектор сказал

«Нитки злые»

для сетевого программирования и рекомендуется использовать асинхронное сетевое программирование с помощью RunLoop. Используйте фоновый stream (параллельная очередь Grand Central Dispatch) для streamовой обработки данных, а не для сетевого программирования.

Кстати, также стоит посмотреть Блоки и Центральные диспетчерские сессии.

  • WWDC 2010 Сессия 206 – Знакомство с блоками и Grand Central Dispatch на iPhone
  • WWDC 2010 Сессия 211 – Упрощение разработки приложений для iPhone с помощью Grand Central Dispatch

Я написал class оболочки для асинхронного NSURLConnection.


AsyncURLConnection.h

 #import  typedef void (^completeBlock_t)(NSData *data); typedef void (^errorBlock_t)(NSError *error); @interface AsyncURLConnection : NSObject { NSMutableData *data_; completeBlock_t completeBlock_; errorBlock_t errorBlock_; } + (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; @end 

AsyncURLConnection.m

 #import "AsyncURLConnection.h" @implementation AsyncURLConnection + (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { return [[[self alloc] initWithRequest:requestUrl completeBlock:completeBlock errorBlock:errorBlock] autorelease]; } - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { if ((self=[super init])) { data_ = [[NSMutableData alloc] init]; completeBlock_ = [completeBlock copy]; errorBlock_ = [errorBlock copy]; NSURL *url = [NSURL URLWithString:requestUrl]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection connectionWithRequest:request delegate:self]; } return self; } - (void)dealloc { [data_ release]; [completeBlock_ release]; [errorBlock_ release]; [super dealloc]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [data_ setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [data_ appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { completeBlock_(data_); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { errorBlock_(error); } @end 

Как использовать class AsyncURLConnection.

 /* * AsyncURLConnection -request:completeBlock:errorBlock: have to be called * from Main Thread because it is required to use asynchronous API with RunLoop. */ [AsyncURLConnection request:url completeBlock:^(NSData *data) { /* success! */ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ /* process downloaded data in Concurrent Queue */ dispatch_async(dispatch_get_main_queue(), ^{ /* update UI on Main Thread */ }); }); } errorBlock:^(NSError *error) { /* error! */ }]; 

Создайте параллельную NSOperation, на которой вы запускаете asynchronous NSURLConnection.

Посмотрите на этот блок кода:

 -(void)getDataFromServer { NSDictionary *dicParams = [NSDictionary dictionaryWithObjectsAndKeys: userId, kUserID, pageIndex,kPageIndex, nil]; NSString *yourURL = [self addQueryStringToUrlString:[NSString stringWithFormat:@"%@/%@",_PATH_,apiName] withDictionary:dicParams]; NSString *queue_id = @"_queue_id_"; dispatch_queue_t queue = dispatch_queue_create([queue_id UTF8String], 0); dispatch_queue_t main = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:yourURL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0]; [theRequest setHTTPMethod:@"GET"]; [theRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [theRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; NSError *serviceError = nil; NSURLResponse *serviceResponse = nil; NSData *dataResponse = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&serviceResponse error:&serviceError]; if(serviceError) { dispatch_sync(main, ^{ // Update your UI if(serviceError.code == -1012){ // Log error }else{ // Log error } }); } else { NSError *jsonError = nil; id dataObject = [NSJSONSerialization JSONObjectWithData:dataResponse options:kNilOptions error:&jsonError]; NSMutableArray *arrResponse = (NSMutableArray *)dataObject; dispatch_sync(main, ^{ // Update your UI [yourTableView reloadData]; }); } }); } +(NSString*)addQueryStringToUrlString:(NSString *)urlString withDictionary:(NSDictionary *)dictionary { NSMutableString *urlWithQuerystring = [[NSMutableString alloc] initWithString:urlString]; for (id key in dictionary) { NSString *keyString = [key description]; NSString *valueString = [[dictionary objectForKey:key] description]; if ([urlWithQuerystring rangeOfString:@"?"].location == NSNotFound) { [urlWithQuerystring appendFormat:@"?%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]]; } else { [urlWithQuerystring appendFormat:@"&%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]]; } } return urlWithQuerystring; } +(NSString*)urlEscapeString:(NSString *)unencodedString { CFStringRef originalStringRef = (__bridge_retained CFStringRef)unencodedString; NSString *s = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,originalStringRef, NULL, NULL,kCFStringEncodingUTF8); CFRelease(originalStringRef); return s; } 
Давайте будем гением компьютера.