AFNetworkReachabilityManager
是用来监测网络状态的类,可以通过设置状态改变回调来获得当前网络状态
网络的状态值有以下四种
1 2 3 4 5 6
| typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1,// 未知 AFNetworkReachabilityStatusNotReachable = 0, // 不可用 AFNetworkReachabilityStatusReachableViaWWAN = 1, // 无线广域网连接 AFNetworkReachabilityStatusReachableViaWiFi = 2, // WiFi连接 };
|
AFNetworkReachabilityManager
提供了五种初始化的方法
可以通过单例方法初始化
1 2 3 4 5 6 7 8 9 10
| + (instancetype)sharedManager { static AFNetworkReachabilityManager *_sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 调用+ manager初始化方法 _sharedManager = [self manager]; });
return _sharedManager; }
|
单例里面调用了第二种通过默认的socket地址初始化方法,返回一个manager对象,sin_family表示协议族,AF_INET表示TCP/IP协议族的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| + (instancetype)manager { #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) struct sockaddr_in6 address; bzero(&address, sizeof(address)); address.sin6_len = sizeof(address); address.sin6_family = AF_INET6; #else // 声明sockaddr_in结构体 struct sockaddr_in address; // address清零 bzero(&address, sizeof(address)); // address赋值 address.sin_len = sizeof(address); address.sin_family = AF_INET; #endif // 调用+ [managerForAddress:]方法 return [self managerForAddress:&address]; }
|
在这里又调用了第三种通过传入一个socket地址来初始化
1 2 3 4 5 6 7 8 9 10
| + (instancetype)managerForAddress:(const void *)address { // 生成SCNetworkReachabilityRef SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); // 调用- [initWithReachability:]方法 AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability); return manager; }
|
里面又调用了第五种初始化方法,因为该方法的后缀里面有NS_DESIGNATED_INITIALIZER
,所以最终都会调到它,这里就是做了初始化的工作,将起始的网络状态定为Unknown
1 2 3 4 5 6 7 8 9 10 11
| - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; if (!self) { return nil; }
_networkReachability = CFRetain(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
return self; }
|
最后剩下一种方法就是可以根据特定的域来初始化
1 2 3 4 5 6 7 8 9
| + (instancetype)managerForDomain:(NSString *)domain { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; CFRelease(reachability);
return manager; }
|
然后在初始化结束之后,我们需要设置网络状态改变的回调,在开启监听之后,会将网络状态回调给外部
1 2 3
| - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { self.networkReachabilityStatusBlock = block; }
|
最后就是开启监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| - (void)startMonitoring { // 停止监听 [self stopMonitoring];
if (!self.networkReachability) { return; }
// 收到callback调用后,将status通过networkReachabilityStatusBlock回调出去 __weak __typeof(self)weakSelf = self; AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { __strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status; if (strongSelf.networkReachabilityStatusBlock) { strongSelf.networkReachabilityStatusBlock(status); }
};
// 声明SCNetworkReachabilityContext结构体 SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; // 设置回调 SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); // 加到Main runloop里面对其进行监测 SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); // 获取当前的网络状态,调用callback dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) { AFPostReachabilityStatusChange(flags, callback); } }); }
|
如果没有设置回调的话,也可以通过注册通知的方式,收到网络状态的变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) { // 获取当前的status AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); dispatch_async(dispatch_get_main_queue(), ^{ // 返回status值 if (block) { block(status); } // 同时会发送一个通知 NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; }); }
|
停止监听的话,就是取消在Main Runloop里面的监听
1 2 3 4 5 6 7
| - (void)stopMonitoring { if (!self.networkReachability) { return; }
SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); }
|
使用方式例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| AFNetworkReachabilityManager *networkManager = [AFNetworkReachabilityManager sharedManager]; [networkManager startMonitoring]; [networkManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusNotReachable: // do something break; case AFNetworkReachabilityStatusReachableViaWWAN: // do something break; case AFNetworkReachabilityStatusReachableViaWiFi: // do something break; default: break; } }];
|