NSURLConnection异步无法正常工作

时间:2014-01-03 03:59:47

标签: ios iphone objective-c asynchronous

我正在尝试创建一个异步NSURL请求,但我得到了所有“FALSE。”

-(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中处理异步和回调,所以非常感谢详细的答案!谢谢!

3 个答案:

答案 0 :(得分:5)

异步调用将并行执行,其结果将在完成块中接收。在您的情况下,将在完成异步请求之前执行return语句。那总是假的。

您应该对此使用同步请求,并且不要阻止UI。

-(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");
});

答案 1 :(得分:2)

您应该意识到此问题本身异步。您无法使用同步方法解决它。也就是说,您接受的解决方案只是一个精心设计和次优的包装器,无论如何最终都会异步。

更好的方法是使用带有完成处理程序的异步方法,例如:

typedef void (^completion_t)(BOOL isReachable);

-(void)checkConnectionForHost:(NSString*)host completion:(completion_t)completionHandler;

您可以实现如下(即使请求不是检查可达性的最佳选择):

-(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";
    });    
}];

答案 2 :(得分:1)

你的isOnline可能被设置为YES,但它是异步发生的。在您注销isOnline的值后几乎肯定会执行。因此,您应该将NSLog()调用移动到作为处理程序传递给异步URL请求的块中。

相关问题