SystemConfiguration网络监测
网络状态监测使用SystemConfiguration这个API 从包含的头文件中可以看到,之前的网络库ASIHttpRequest中的网络状态监测类Reachability也是对SystemConfiguration的一层封装,AFNetworkReachabilityStatus 代表获取到的网络状态
的
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1, // 位置
AFNetworkReachabilityStatusNotReachable = 0, //无网络 不能连接
AFNetworkReachabilityStatusReachableViaWWAN = 1, // 蜂窝网
AFNetworkReachabilityStatusReachableViaWiFi = 2, //WIFI
};
以下两个宏代表在他们中间的参数默认是nonnull类型的,相当于程序猿做的标记,用于交流这几个参数不能为空
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
这张图可以反映出本篇的大致实现过程
Paste_Image.png初始化manager
Paste_Image.png一共五种方式 其实从etworkReachabilityRef的创建方式来看可以说是两种
+ (instancetype)managerForDomain:(NSString *)domain {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
+ (instancetype)managerForAddress:(const void *)address {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
block方式获取状态
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem;
通知方式
/**
Sets a callback to be executed when the network availability of the `baseURL` host changes.
@param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`.
// 设置网络状态回调
*/
- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block;
开始监听
- (void)startMonitoring {
[self stopMonitoring];
if (!self.networkReachability) {
return;
}
__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);
// 加入RunLoop
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
// 异步发送网络状态
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
AFPostReachabilityStatusChange(flags, callback);
}
});
}
SCNetworkReachabilityFlags 转为 AFNetworkReachabilityStatus
通过开发监听那个方法可以获取到系统返回的SCNetworkReachabilityFlags值
接下来看下如何进行转换 这是一个同步的方法
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) {
// 是否能够连接
BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
// 在联网之前需要建立连接
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
// 是否可以自动连接
BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));
// 是否可以连接,在不需要用户手动设置的前提下
BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0);
// 是否可以联网的条件 1.能够连接 2.不需要建立连接或者不需要用户手动设置连接 就表示能够连接到网络
BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction));
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;
if (isNetworkReachable == NO) {
status = AFNetworkReachabilityStatusNotReachable;
}
#if TARGET_OS_IPHONE
else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
status = AFNetworkReachabilityStatusReachableViaWWAN;
}
#endif
else {
status = AFNetworkReachabilityStatusReachableViaWiFi;
}
return status;
}
取消监听
- (void)stopMonitoring {
if (!self.networkReachability) {
return;
}
// 停止监控
SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
网友评论