网络可达性变更事件未触发

5

我的 iPhone 应用程序非常简单,只有一个视图来处理所有事情,在 viewDidLoad 中我检查是否有网络连接,如果有,我们从网络加载数据,否则我们从本地资源加载。这样就可以正常运行。

//in viewDidOnload    
[[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@selector(handleNetworkChange:) 
                                          name:kReachabilityChangedNotification object:nil];
reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
NetworkStatus status = [reachability currentReachabilityStatus];

if (status == NotReachable) {
    //Do something offline
} else {
    //Do sometihng on line
}

- (void)handleNetworkChange:(NSNotification *)notice{
 NetworkStatus status = [reachability currentReachabilityStatus];
 if (status == NotReachable) {
  //Change to offline Message
 } else {
  //Relaunch online application
 }

}

为了测试我的handleNetworkChange事件,我关闭了所有蜂窝数据但保留了WiFi。在WiFi范围内启动应用程序,一切都很完美。然后我走出WiFi的范围,但我的handleNetworkChange从未触发(使用uiAlertView进行测试)。在WiFi范围外,我的应用程序可以正常启动离线消息。
我怀疑这是ViewController生命周期的问题,这段代码是否应该放在AppDelegate函数中?也许这是一个更好的设计起点。

我认为NSNotification行应该在初始化reachability实例之后声明。 - Raptor
4个回答

18

结果证明这是一个内存管理问题,因为我没有保留可达性变量,所以一旦它超出了范围,dealloc就会被调用并调用stopNotifier方法。因此,当我走出范围时就没有更新。

因此,不应该:

reachability = [Reachability reachabilityForInternetConnection];

我做

reachability = [[Reachability reachabilityForInternetConnection] retain];

而且一切都可以正常工作!

我从中学到的一个酷技巧是,在模拟器中,你可以通过简单地关闭“无线局域网”来模拟失去连接的情况。再也不用在外面到处闲逛了。:)


我需要在某个时候释放它吗?可能是在我的视图控制器的dealloc中吗? - ashansky
1
在这种情况下,您必须在某个地方保持reachability对象的强引用(例如作为您的ViewController类的@property),以便保留它。 - fatuhoku

0

看一下苹果的可达性示例。我相信他们在AppDelegate中启动通知。在我的一个应用程序中,我创建了一个布尔变量,它通过AppDelegate连接更新方法不断更新,因此在我的其他视图控制器中,我只需要调用委托并检查IsConnected bool的值。

再提出另一个想法...我注意到可达性类存在问题,当您检查可达性时,它可能会冻结您的应用程序。在我的新应用程序中,我完全跳过可达性类,而是依靠NSUrlConnection和UIWebView的DidFail委托方法来确定是否具有真正的连接性。我不再需要等待可达性类弄清楚并为我失败,然后再决定该怎么做,我只需继续进行网络调用并使用本地作为备选方案。

希望这可以帮助!


嗯,我一定做错了什么事情。我尝试将它移动到AppDelegate中,但仍然没有任何反应... - ashansky

-1
你应该将 systemconfiguration.framework 包含到你的项目中。

-2

您的应用程序未在后台运行。

请在您的委托类中添加此方法。

- (void)applicationDidEnterBackground:(UIApplication *)application
{ UIApplication* app = [UIApplication sharedApplication];

    UIBackgroundTaskIdentifier __block bgTask = [app beginBackgroundTaskWithExpirationHandler: ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        });
    }];

}

谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接