为啥可达性示例应用程序在这里停滞不前?

Posted

技术标签:

【中文标题】为啥可达性示例应用程序在这里停滞不前?【英文标题】:Why does Reachability sample app stall here?为什么可达性示例应用程序在这里停滞不前? 【发布时间】:2009-04-06 22:14:29 【问题描述】:

Apple 名为 Reachability 的示例应用程序展示了如何检测连接。如果您只有 wifi 而没有互联网,应用程序会在下面的第二行停止超过一分钟:

SCNetworkReachabilityFlags reachabilityFlags;
BOOL gotFlags = SCNetworkReachabilityGetFlags(reachabilityRef, &reachabilityFlags);

SCNetworkReachabilityGetFlags 来自 SystemConfiguration.framework。有关如何解决此问题的任何建议?

【问题讨论】:

【参考方案1】:

要直接回答您的问题,不,似乎没有任何方法可以“绕过” SCNetworkReachabilityGetFlags() 在您描述的特定情况下需要很长时间才能返回(例如,通过 WiFi 连接检查远程主机可访问性到没有互联网的路由器)。几个选项:

选项 1. 在单独的线程中进行调用,以便您的应用程序的其余部分可以继续运行。修改 ReachabilityAppDelegate.m 示例如下:

// Modified version of existing "updateStatus" method
- (void)updateStatus

    // Query the SystemConfiguration framework for the state of the device's network connections.
    //self.remoteHostStatus           = [[Reachability sharedReachability] remoteHostStatus];
    self.remoteHostStatus = -1;
    self.internetConnectionStatus   = [[Reachability sharedReachability] internetConnectionStatus];
    self.localWiFiConnectionStatus  = [[Reachability sharedReachability] localWiFiConnectionStatus];
    [tableView reloadData];

    // Check remote host status in a separate thread so that the UI won't hang
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSTimer *timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(updateRemoteHostStatus) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [pool release];

// New method
- (void) updateRemoteHostStatus

    self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus];
    [tableView reloadData];

选项 2. 在尝试连接到远程主机时使用使用超时值的不同 API/函数。这样一来,您的应用只会挂起 X 秒后放弃。

其他一些注意事项:

您询问的对 SCNetworkReachabilityGetFlags() 的特定调用(即 Reachability.m 中的第 ~399 行)试图查看 www.apple.com 是否“可访问”以推断“外部互联网”是否为“可达”一般。 在 Apple 的系统配置框架中,“可访问”可能并不意味着您认为它的作用。根据官方文档,“可达”似乎意味着,理论上,您的计算机可以根据需要连接到主机 X,但它可能需要先实际建立连接(例如,先拨打调制解调器)。换句话说,SCNetworkReachabilityGetFlags() 实际上并没有建立连接。

【讨论】:

谢谢。如何创建超时,以便在达到超时间隔时返回回调?如果在超时间隔之前调用 UIWebViewDelegate::webViewDidFinishLoad,我可以取消超时。 看看 NSTimer 的 scheduleTimerWithTimeInterval: 方法。您可以在当前线程中创建一个计时器,例如,在 5 秒后执行某个方法。此方法可以检查 SCNetworkReachabilityGetFlags() 是否已完成,如果尚未完成,则运行您的超时逻辑。

以上是关于为啥可达性示例应用程序在这里停滞不前?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 可达性和应用挂起/恢复行为

在后台检测可达性

暂停应用程序的可达性更改 iOS 系统通知

在单元测试中使用 AFNetworking 监控可达性失败

为啥 Petri 网的可达性图中未定义最终标记的数量?

寻找可达性(2.0)用例验证