AFNetworking 2.0 可达性

36

我正在尝试使用AFNetworking 2.0和“AFNetworkReachabilityManager”确定用户是否连接到互联网,但似乎不起作用。它总是返回有有效的互联网连接,即使网络关闭了。

这是我的代码:

 -(BOOL)connected {

   __block BOOL reachable;

    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

        switch (status) {
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"No Internet Connection");
                reachable = NO;
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"WIFI");

                reachable = YES;
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"3G");
                reachable = YES;
                break;
            default:
                NSLog(@"Unkown network status");
                reachable = NO;
                break;

                [[AFNetworkReachabilityManager sharedManager] startMonitoring];
        }
    }];

    return reachable;

}

这个方法是从我的viewDidLoad方法调用的。由于它没有起作用,我的代码有什么问题吗?


为什么不使用苹果提供的示例?https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html - Mat
38
因为我使用AFNetworking。但还是谢谢你的评论 :) - 7c9d6b001a87e497d6b96fbd4c6fdf
2
请确保执行以下代码:[[AFNetworkReachabilityManager sharedManager] startMonitoring]; - Jeremie D
7个回答

101

你让这变得比必要的更困难。试试这个:

- (void)viewDidLoad {
   [super viewDidLoad];

   [[AFNetworkReachabilityManager sharedManager] startMonitoring];

}

- (BOOL)connected {
    return [AFNetworkReachabilityManager sharedManager].reachable;
}   

如果您也希望在状态更改时收到通知,则需要实现setReachabilityStatusChangeBlock


这个完美运行。我不需要在我的.pch文件中#import <SystemConfiguration/SystemConfiguration.h>。记得在实际设备上测试,因为在iOS模拟器中它似乎总是返回true - Alex
6
模拟器只会返回您计算机的状态。尝试断开网络,您就会看到。 - mikker
@mikker 问题在于稍后关闭Mac上的WiFi似乎不会触发状态更改块。它仅适用于初始检查。 - user3344977

64

那是因为该代码块仅在可达性状态更改时执行。

要获取当前状态,您可以执行以下操作:

- (BOOL)connected {
    return [AFNetworkReachabilityManager sharedManager].reachable;
}

2
谢谢你的回答。然而它似乎不起作用,即使WIFI和3G已经打开或关闭,它总是返回NO(未连接)。你有什么想法为什么会发生这种情况吗? - 7c9d6b001a87e497d6b96fbd4c6fdf
1
这是当前的状态。也许您想要监听AFNetworkingReachabilityDidChangeNotification或使用reachabilityStatusChangeBlock获取更新。 - Marcelo
6
你是在实际设备上运行,还是在模拟器中运行?模拟器并不总是知道自己的网络可用性。 - Johanneke
请查看下面的答案。您应该在viewDidLoad中开始监视,并给它一点时间来检查连通性。 - anders
这总是返回 FALSE :( - Chetan Prajapati
有人说这个不起作用,可以看看这个答案:http://stackoverflow.com/a/35497418/1679519 - Bernard

11

你的代码存在两个错误,这将导致你的代码无法正常工作。

首先,“开始监控”的调用发生在响应到达性更改的块内部,因此,除非在其他地方开始监控,否则该块永远不会触发。

其次,不能保证该块何时触发。因此,你将始终看到“可达”返回初始化为什么值就是什么值的结果--显然通常是null。即使你修复了第一个错误,在返回之前也没有保证(实际上相当不可能)块将触发。

最后,在更一般的层面上,你还尝试以同步的方式测试只能异步执行的代码。也就是说,可达性管理器不可能立即准确地确定可达性。它可以说“我认为我正在使用WiFi”或“我认为我正在使用3G”,但它还需要检查是否可以实际通过连接到互联网(因此称为可达性),然后才能确定。可达性不仅涉及“我有wifi”或“我有3g”连接,还涉及你是否可以通过它接入互联网。这意味着设备实际上必须发送请求,虽然这可以以同步方式完成,但书中的每一条规则都坚持网络代码必须异步执行,原因很充分。如果你同步地完成它,你会阻塞你的UI,直到网络调用返回...可能会花费30、40、50甚至60秒,这取决于相关的超时。

你应该在应用程序委托的did load方法中开始单例监控可达性,然后稍后检索它的数据。我不知道你的应用程序结构,所以我甚至不会保证准确性,但至少应该有所帮助。


1
这应该是被接受的答案!非常有帮助,谢谢。 - rtcarlson

7

试试这个:

AppDelegate中的didFinishLaunchingWithOptions方法中。

{ // SETUP AFNETWORKING's NETWORK INDICATOR AND REACHABILITY
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

HttpManager 类中,
- (BOOL)isNetworkRechable {

    if ([AFNetworkReachabilityManager sharedManager].reachable) {

        if ([AFNetworkReachabilityManager sharedManager].isReachableViaWiFi)
            NSLog(@"Network reachable via WWAN");
        else
            NSLog(@"Network reachable via Wifi");

        return YES;
    }
    else {

        NSLog(@"Network is not reachable");
        return NO;
    }
}

yourViewController中,
[[HttpManager sharedObject] isNetworkRechable];

注意:在最开始不要检查networkRechability,因为这样做是行不通的。请等待至少1秒再进行检查。


好的解决方案,值得赞赏。 - Rahul K Rajan
不错的解决方案。谢谢@Balaji G - Matic1911

6
根据我的经验,
[[AFNetworkReachabilityManager sharedManager] startMonitoring];

执行setReachabilityStatusChangeBlock需要一点时间,因此从-(BOOL)connected中返回值是没有用的。

因此,您可以在网络连接/断开后执行某些任务。

以下函数最适合即时检查连接状态(同步):

[AFNetworkReachabilityManager sharedManager].reachable;

3
其他答案是错误的!使用以下内容检查可用性更好:
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable)

之所以如此,是因为最初networkReachabilityStatus将被设置为AFNetworkReachabilityStatusUnknown,直到更改状态块被调用,这可以防止您的代码在网络可用时认为网络不可用。


1
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    [self checkNetworkReachability];
}    


+(BOOL) isReachable{
   return [AFNetworkReachabilityManager sharedManager].reachable;
}

+(void) checkNetworkReachability{
        [[AFNetworkReachabilityManager sharedManager] startMonitoring];
        [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));

            // Check the reachability status and show an alert if the internet connection is not available
            switch (status) {
                case -1:
                    // AFNetworkReachabilityStatusUnknown = -1,
                    NSLog(@"The reachability status is Unknown");
                    break;
                case 0:
                    // AFNetworkReachabilityStatusNotReachable = 0
                    NSLog(@"The reachability status is not reachable");
                    break;
                case 1:
                    NSLog(@"The reachability status is reachable via wan");
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"Network_Reachable" object:nil];
                    break;
                case 2:
                    // AFNetworkReachabilityStatusReachableViaWiFi = 2
                    NSLog(@"The reachability status is reachable via WiFi");

                    [[NSNotificationCenter defaultCenter] postNotificationName:@"Network_Reachable" object:nil];
                    break;

                default:
                    break;
            }

        }];
    }

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