我正在尝试学习 AFNetworking。当我运行以下代码时,我发现没有互联网。但在另一项检查中,它说它已连接到互联网,并且设备已通过 wifi 连接到互联网。这是输出:
2016-02-19 15:16:40.315 AFNetworkingSample[377:47927] There is no internet connection
2016-02-19 15:16:40.331 AFNetworkingSample[377:47927] Reachability: Reachable via WiFi
知道为什么连接方法的返回值是 false 吗?
- (void)viewDidLoad {
[super viewDidLoad];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
}];
}
-(BOOL)connected {
return [AFNetworkReachabilityManager sharedManager].reachable;
}
更新 当我将其更改为以下时,它可以正常工作并正确检测到互联网。谁能解释这种行为?
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
}];
更新 2
当我等待两秒钟时,它会正确检测到互联网:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
});
更新 3:
这是避免竞争条件的练习方法吗?
- (void)viewDidLoad {
[super viewDidLoad];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
if([AFNetworkReachabilityManager sharedManager].reachable)
{
NSLog(@"Internet connection started again");
}
else
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert"
message:@"Error Retrieving Data"
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *firstAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
NSLog(@"You pressed button OK");
}];
[alert addAction:firstAction];
[self presentViewController:alert animated:YES completion:nil];
}
}];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
});
}
最佳答案
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
以上实际上是一个异步 调用。您已经告诉 AFNetwork
您对可达性感兴趣。因此,它将关闭并做任何它需要做的事情来确定和监控后台的可达性。
因为它不是一次性异步调用,所以在该方法上有一个完成 block 并不真正适合普通完成处理程序的模式。它可能是一个“状态处理程序”,只要状态发生变化就会被调用,但该 API 也被设计用于被动轮询(您的其他一些代码模式,如计时器模式,无意中这样做 - 并且,如您所述,如预期的那样,等待时间不够长会给您错误的答案。
通过调用 setReachabilityStatusChangeBlock:
,您注册了一些代码,以便在可达性状态更改时执行。用它来触发你的“嘿!可达性改变了!”代码,一切正常。
唯一剩下的问题是是否存在竞争条件。您应该在调用 startMonitoring
之前设置 block 。而且,为了安全起见,您可能希望在调用 startMonitoring
后立即检查网络是否已连接,因为从技术上讲,如果网络已连接,则状态可能不会发生变化触发对状态更改处理程序 block 的调用。
您不想阻塞线程 2 秒来尝试避免竞争条件。做这样的事情:
... set up change handler block ...
... start monitoring ...
... check current internet state & alert user if necessary ...
将您的警报从更改处理程序 block 中移出,并转移到更改处理程序 block 和上面提到的“检查当前互联网状态并在必要时提醒用户”都可以调用的方法中。
关于ios - 为什么 Reachability Manager 无法检测到互联网?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35497269/