无网络情况后,可达性导致崩溃 - 如何异步正确使用可达性

Mar*_*ian 7 iphone reachability

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

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

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

}

我正在调用与viewDidAppear调用的方法同步.

    if ([self reachable]== YES) {
        ... do network stuff ...
Run Code Online (Sandbox Code Playgroud)

它基于iOS 4 Reachability Guide的代码

我的问题:是否正确使用Reachability它将处理此错误并处理缺少3G或Wifi网络?我是否需要生成另一个线程或执行某些操作来删除同步调用?

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


Application Specific Information:
(app name) failed to resume in time

Elapsed total CPU time (seconds): 3.280 (user 1.770, system 1.510), 33% CPU 
Elapsed application CPU time (seconds): 0.040, 0% CPU

Thread 0 name:  Dispatch queue: com.apple.main-thread
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   SystemConfiguration             0x311b4256 __SCNetworkReachabilityGetFlags + 962
7   SystemConfiguration             0x311b4f1e SCNetworkReachabilityGetFlags + 98

Joe*_*oel 5

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

Apple甚至在Reacahbility示例代码中对此进行了警告:

苹果可达性示例代码README

就像在Reachability示例应用程序中一样使用通知---它运作良好,并且一旦您使用了NSNotificationCenter设计模式,它就非常简单。

祝好运!


Mar*_*ian -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];
Run Code Online (Sandbox Code Playgroud)

调用的方法看起来像这样

- (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 ...      
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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

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