AFNetworkReachabilityManager是用来监测网络状态,网络状态管理的类,他可以通过设置状态改变回调来获得当前网络状态。
//网络的状态分四种
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1, //未知
AFNetworkReachabilityStatusNotReachable = 0, //无网络
AFNetworkReachabilityStatusReachableViaWWAN = 1, //蜂窝网络
AFNetworkReachabilityStatusReachableViaWiFi = 2, //WiFi
};
一、属性
公有属性(.h中的)
// 当前网络的状态,就是枚举中的类型
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
//当前网络是否可用(蜂窝网或WiFi)
@property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable;
//当前网络是否是蜂窝网
@property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
//当前网络是否是WiFi
@property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
私有属性(.m中的)
//用来保存创建测试连接返回的引用
@property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability;
//网络状态
@property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
二、初始化
AFNetworkReachabilityManager的初始化方法有5种
1、单例初始化
+ (instancetype)sharedManager {
static AFNetworkReachabilityManager *_sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedManager = [self manager]; //调用了+ manager方法
});
return _sharedManager;
}
2、在第一个单例方法中调用了此方法,通过默认的socket地址初始化,返回一个manager对象,sin_family表示协议族,AF_INET表示TCP/IP协议族的地址。
+ (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
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
#endif
return [self managerForAddress:&address];
}
3、在第二种方法里面又调用了此方法,通过传入一个socket地址来初始化。
+ (instancetype)managerForAddress:(const void *)address {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
4、在第三种方法里面,又调用了第四种初始化方法,因为该方法的后缀里面有NS_DESIGNATED_INITIALIZER,所以最终都会调到它,这里就是做了初始化的工作,将起始的网络状态定为Unknown。
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
self = [super init];
if (!self) {
return nil;
}
_networkReachability = CFRetain(reachability);
self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
return self;
}
5、这种方法就是可以根据特定的域来初始化。
+ (instancetype)managerForDomain:(NSString *)domain {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
三、开始监听、停止监听
1、开始监听方法
- (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);
}
});
}
2、停止监听方法
- (void)stopMonitoring {
if (!self.networkReachability) {
return;
}
SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
四、应用(demo)
//监测网络状态的方法
- (void)monitorReachabilityStatus
{
// 开始监测
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
// 网络状态改变的回调
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"蜂窝网络");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"没有网络");
break;
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
default:
break;
}
}];
}