AFNetworking 3.0 源码解析之Reachability
来源:互联网 发布:wps表格删除筛选数据 编辑:程序博客网 时间:2024/05/17 12:25
Reachability这部分主要负责网络的状态网络状态的监听。
这里介绍下使用方法。
1.直接使用单利,调用
AFNetworkReachabilityManager *reachabilityManager = [AFNetworkReachabilityManager sharedManager]; [reachabilityManager startMonitoring]; [reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { NSLog(@"status %ld", (long)status); }];
2.使用AFURLSessionManager的属性调用
AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"https://www.baidu.com"] sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer]; [sessionManager.reachabilityManager startMonitoring]; [sessionManager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { NSLog(@"status %ld", (long)status); }];
3.使用通知中心的模式,监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityCallBack:) name:AFNetworkingReachabilityDidChangeNotification object:nil]; (void)reachabilityCallBack:(NSNotification *)sender { NSDictionary *userInfo = sender.userInfo; AFNetworkReachabilityStatus netStatus = [userInfo[@"AFNetworkingReachabilityNotificationStatusItem"] integerValue]; NSLog(@"netStatus %ld ", netStatus);
使用方法还是比较简单的
下面分析下源码。
1.初始化网络监听
+ (instancetype)sharedManager; + (instancetype)manager; + (instancetype)managerForDomain:(NSString *)domain; + (instancetype)managerForAddress:(const voidvoid *)address; - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER;
以上均是初始化方法,我们可以直接用单利模式,比较方便的进行初始化对象,也可以直接用manager,建议还是用单利,因为单利里面也是调用的manager:
+ (instancetype)sharedManager { static AFNetworkReachabilityManager *_sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedManager = [self manager]; }); return _sharedManager; }
manager是直接使用的managerForAdress方法:
+ (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]; }
当然我们也可以使用初始化domain的方法,然后转换成SCNetworkReachabilityRef对象,进行初始化:
+ (instancetype)managerForDomain:(NSString *)domain { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; CFRelease(reachability); return manager; }
初始化方法里面只是做了一个retain,和初始化网络状态,目测SCNetworkReachabilityRef是不支持自动内存管理的。
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; if (!self) { return nil; } _networkReachability = CFRetain(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; return self; }
2.开始监听网络状态
我们之间调用startMonitoring方法,进行开始网络状态的监控:
- (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 context = {0, (__bridge voidvoid *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 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); } }); }
使用方法比较简单,此处我们可以看到,做了数据保护工作,如果没有初始化会return,首先先stopMonitoring,这样做可以避免生成多个监听网络的对象,导致收到多个成功的回调。
然后是一个网络状态捕获到的回调。
下面才是使用的SystemConfiguration框架下的SCNetworkReachability的API来做的处理,使用也比较简单,先初始化,然后设置回调block,再对回调的C数据转换成网络状态的枚举类型,最后放到了RunLoop里面,设置到了主RunLoop,并设置model为CommonModes,CommonModes就是普通的和事件处理Mode的集合,不清楚的可以去看RunLoop相关文档。
3.结束监听网络状态
结束也比较简单,当然,我们可以自己调用,也可以不调用。因为在类销毁的时候,dealloc中也调用了这个方法。
- (void)stopMonitoring { if (!self.networkReachability) { return; } SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); }
再看一下网络状态的枚举吧,也就是我们可以捕获到的网络状态有哪些:
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1, AFNetworkReachabilityStatusNotReachable = 0, AFNetworkReachabilityStatusReachableViaWWAN = 1, AFNetworkReachabilityStatusReachableViaWiFi = 2, };
默认是Unknown未知,然后是网络不可达,无线广域网链接,WiFi链接,此处没有区分2G/3G/4G,所以需要使用的小伙伴还得自行处理。
当然AF也为我们提供了获取的属性方法,我们可以直接调用:
@property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; /** Whether or not the network is currently reachable via WWAN. */ @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; /** Whether or not the network is currently reachable via WiFi. */ @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
实现:
- (BOOL)isReachable { return [self isReachableViaWWAN] || [self isReachableViaWiFi]; } - (BOOL)isReachableViaWWAN { return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; } - (BOOL)isReachableViaWiFi { return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; }
我们可以看到,我们可以拿到网络是不是可达,当前是不是状态WWAN,WiFi。使用比较方便。
基本就是这些了,如果文中有什么错误,欢迎大家指正。
- AFNetworking 3.0 源码解析之Reachability
- AFNetworking 3.0 源码解析之Reachability
- AFNetworking 3.0 源码解析之Serialization
- AFNetworking 3.0 源码解析之NSURLSession
- AFNetworking 源码解析之“AFURLSessionManager”
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<四>
- AFNetworking源码解析<四>
- AFNetworking源码解析https
- AFNetworking源码解析<三>
- AFNetworking-源码解析
- AFNetworking源码解析<三>
- AFNetworking源码解析<四>
- AFNetworking源码解析<三>
- AFNetWorking源码解析
- AFNetworking源码解析<三>
- Linux在nanopi m3的安装配置
- 链表操作
- 使用sql语句创建修改SQL Server表id自增
- NameError: name 'mnist' is not defined
- vue使用less识的scoped属性
- AFNetworking 3.0 源码解析之Reachability
- java判断两条线是否相交
- boost asio 异步io
- 九、Python之函数
- 关于自增自减运算符的一些问题
- 正则表达式学习
- webuploader上传附加参数formData注意
- TCP状态表示及其含义
- django学习——如何配置404、500页面