NSURLConnectionasynchronous不起作用
我试图做一个asynchronousNSURL请求,但我得到所有“假”。
-(BOOL)checkConnectionForHost:(NSString*)host{ BOOL __block isOnline = NO; NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:host] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:1]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if([(NSHTTPURLResponse*)response statusCode]==200){ isOnline = TRUE; } }]; NSLog(@"%i",isOnline); return isOnline; }
此外,这个代码被称为“6”次,当我实际上只是用它:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
并且在我的数据源中只有3个单元格或3个项目。 第一次在Objective-C中处理asynchronous和callback,所以一个详细的答案将不胜感激! 谢谢!
你应该认识到这个问题本质上是asynchronous的。 你不能用同步方法来解决它。 也就是说,您接受的解决scheme只是一个精心制作的,不太理想的包装,最终会导致asynchronous。
更好的方法是使用完成处理程序的asynchronous方法,例如:
typedef void (^completion_t)(BOOL isReachable); -(void)checkConnectionForHost:(NSString*)host completion:(completion_t)completionHandler;
您可以实现如下(即使请求不是检查可达性的最佳select):
-(void)checkConnectionForHost:(NSString*)host completion:(completion_t)completionHandler { NSURLRequest* request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:host]]; [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (completionHandler) { completionHandler(connectionError == nil && [(NSHTTPURLResponse*)response statusCode]==200); } }]; }
请注意:
- 不要将超时设置为与原始代码一样短。
- 完成处理程序将在一个专用线程上被调用。
用法:
[self checkConnectionForHost:self.host completion:^(BOOL isReachable){ dispatch_async(dispatch_get_main_queue(), ^{ self.reachableLabel.text = isReachable ? @"" : @"Service unavailable"; }); }];
asynchronous调用将并行执行,其结果将在完成块中接收。 在你的情况下,return语句将在asynchronous请求完成之前执行。 这将永远是假的。
您应该为此使用同步请求,并处理不阻止用户界面。
-(BOOL)checkConnectionForHost:(NSString*)host{ BOOL isOnline = NO; NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:host] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:1]; NSHTTPURLResponse *response; NSError *error; NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; NSLog(@"Response status Code : %d",response.statusCode); isOnline = response.statusCode == 200; return isOnline; }
您可以在派遣队列中使用该方法,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul); dispatch_async(queue, ^{ BOOL status = [self checkConnectionForHost:@"http://google.com"]; NSLog(@"Host status : %@",status ? @"Online" : @"Offline"); });
你的isOnline
可能被设置为YES,但它是asynchronous发生的。 在注销isOnline
的值后,它几乎肯定会执行。 所以你应该把你的NSLog()
调用到你传递给asynchronousURL请求的处理程序的块中。