我正在尝试创建一个异步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中处理异步和回调,所以非常感谢详细的答案!谢谢!
答案 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请求的块中。