7

我在开发中的 iPhone 应用程序时遇到了一个非常奇怪的崩溃。似乎每次我向朋友展示我的应用程序时它都会崩溃,但否则它永远不会崩溃。在对墨菲定律方面普遍感到困惑之后,我确定了撞车的模式——纽约市地铁。使用地铁后,我的应用程序经常崩溃。我已经将问题追溯到我使用Reachability. 该应用程序在无网络情况下(不包括飞行模式)使用后下次崩溃。在执行任何其他网络操作之前​​,我会遵循 Apple 的指南并检查是否存在连接Reachability,但我发现了一些关于如何调用它的相互冲突的文档。

目前我正在做这样的事情:

-(BOOL)reachable {
    Reachability *r = [Reachability reachabilityWithHostName:@"www.stackoverflow.com"];
    NetworkStatus internetStatus = [r currentReachabilityStatus];
    if(internetStatus == NotReachable) {
        return NO;
    }
    return YES;

}

我正在使用从 viewDidAppear 调用的方法同步调用它。

    if ([self reachable]== YES) {
        ... do network stuff ...

它基于iOS 4 可达性指南中的代码

我的问题:是否正确使用Reachability它可以解决这个错误并处理没有 3G 或 Wifi 网络的情况?我是否需要生成另一个线程或做一些事情来删除同步调用?

顺便说一下,这里是我的应用程序崩溃时看到的崩溃日志,这让我认为这是一个同步/异步问题。

应用特定信息:
(应用名称)未能及时恢复

已用总 CPU 时间(秒):3.280(用户 1.770,系统 1.510),33% CPU
已用应用程序 CPU 时间(秒):0.040,0% CPU

线程 0 名称:调度队列:com.apple.main-thread
线程 0:
0 libsystem_kernel.dylib 0x30747fbc kevent + 24
1 libsystem_info.dylib 0x30abec4e _mdns_search + 586
2 libsystem_info.dylib 0x30abfb72 mdns_addrinfo + 370
3 libsystem_info.dylib 0x30abfd68 search_addrinfo + 76
4 libsystem_info.dylib 0x30ac1bcc si_addrinfo + 1080
5 libsystem_info.dylib 0x30abd0b2 getaddrinfo + 78
6 系统配置 0x311b4256 __SCNetworkReachabilityGetFlags + 962
7 系统配置 0x311b4f1e SCNetworkReachabilityGetFlags + 98
4

2 回答 2

5

在同步情况下,您可能会被 iOS 应用程序看门狗杀死。这是因为要进行可达性检查,SCNetworkReachability 功能需要进行 DNS 查找,这可能需要 30 秒。如果检查主线程上的可达性(即在 viewDidAppear 中)您可能会阻塞主线程很长时间,iOS 会认为您的应用程序已挂起,应用程序看门狗会在 20 秒后将其杀死。

Apple 甚至在 Reacahbility 示例代码中对此提出警告:

Apple 可达性示例代码自述文件

只需使用 Reachability 示例应用程序中的通知——它运行良好,并且在您了解 NSNotificationCenter 设计模式后非常简单。

祝你好运!

于 2011-09-23T20:11:09.500 回答
-1

我通过将其设置为异步解决了我的问题。我调用这样的方法

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSTimer *timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(loadData) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[pool release];

并且调用的方法看起来像这样

- (void)loadData {
    // check for reachability first before starting data load
    if ([self reachable]== NO) {
        // display error message that there is no internet connection, e.g.
        UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Connection Error" message:@"Cannot load data.  There is no internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Retry",nil];
        [errorAlert show];
        [errorAlert release];
    } else {
        // do something to load data from internet ...      
    }

}

使用与上面相同的可访问代码。

我想说总是像这样使用可达性——苹果给出的例子是不完整的。我已经在一个完整的应用程序上运行了几个月的代码,它非常稳定。

编辑: 从 iOS 5 开始,此代码不再稳定——它现在有时会由于“超出允许时间的活动断言”而崩溃。自从我写了这个问题以来,Apple 已经更新了他们的文档和示例代码,所以我建议在另一个答案中点击链接。

于 2011-07-15T14:30:46.383 回答