名次解释
1、AFNetworking:AFNetworking是一款在OS X和iOS下都令人喜爱的网络库
github地址:https://github.com/AFNetworking/AFNetworking.git
2、我们从最常用的监控网络请求开始
这时是创建单例的流程
1、创建单例
+ (instancetype)managerForAddress:(const void *)address {
//创建了id类型的reachability
//reachability表示的是需要检测的网络地址的句柄
//通过SCNetworkReachabilityCreateWithAddress函数创建句柄
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
return manager;
}
2、初始化操作
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
self = [super init];
if (!self) {
return nil;
}
//保存监控网络的句柄
self.networkReachability = CFBridgingRelease(reachability);
//设置初始网络状态
self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
return self;
}
3、调用startMonitoring方法开始网络监控
(1)先调用stopMonitoring方法将当前监控网络请求的句柄从runloop中移除
- (void)stopMonitoring {
if (!self.networkReachability) {
return;
}
//将句柄为networkReachability 从runloop中移除
SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
(2)根据当前的网络状态来设置回调函数callback
__weak __typeof(self)weakSelf = self;
// 根据网络状态status来设置网络状态监听的回调函数callback
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
(3)创建SCNetworkReachabilityContext类型的上下文结构体
/** context是一个结构体
typedef struct {
// 创建一个SCNetworkReachabilityContext结构体时,需要调用SCDynamicStore的创建函数,而此创建函数会根据version来创建出不同的结构体,SCNetworkReachabilityContext对应的version是0
CFIndex version;
// 下面两个block(release和retain)的参数就是info,此处表示的是网络状态处理的回调函数
void * __nullable info;
// 该retain block用于对info进行retain,下面那个AFNetworkReachabilityRetainCallback核心就是调用了Block_copy(用于retain一个block函数,即在堆空间新建或直接引用一个block拷贝)
const void * __nonnull (* __nullable retain)(const void *info);
// 该release block用于对info进行release,下面那个AFNetworkReachabilityReleaseCallback核心就是调用了Block_release(用于release一个block函数,即将block从堆空间移除或移除相应引用)
void (* __nullable release)(const void *info);
// 提供info的description,此处调用为NULL
CFStringRef __nonnull (* __nullable copyDescription)(const void *info);
} SCNetworkReachabilityContext;
*/
SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
version:// 创建一个SCNetworkReachabilityContext结构体时,需要调用SCDynamicStore的创建函数,而此创建函数会根据version来创建出不同的结构体,SCNetworkReachabilityContext对应的version是0
info:下面两个block(release和retain)的参数就是info,此处表示的是网络状态处理的回调函数
retain:该retain block用于对info进行retain,下面那个AFNetworkReachabilityRetainCallback核心就是调用了Block_copy(用于retain一个block函数,即在堆空间新建或直接引用一个block拷贝)const void * __nonnull (* __nullable retain)(const void *info);
release:该release block用于对info进行release,下面那个AFNetworkReachabilityReleaseCallback核心就是调用了Block_release(用于release一个block函数,即将block从堆空间移除或移除相应引用)
copyDescription: 提供info的description,此处调用为NULL
(4)给客户端指定对应target(该参数和需要检测网络状况的地址有一定关联,此处使用的是self.networkReachability),然后当这个target的网络状态变化时,告之SCNetworkReachabilityCallBack对象callout处理(此处使用的是AFNetworkReachabilityCallback),另外callout中使用到的参数包括target和context提供的info。
/*
Boolean
SCNetworkReachabilitySetCallback (
SCNetworkReachabilityRef target,
SCNetworkReachabilityCallBack __nullable callout,
SCNetworkReachabilityContext * __nullable context
) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);
*/
SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context);
(5)将该监控加入到runloop 中 此方法与stopMonitoring相对应
// 此处表示在main RunLoop中以kCFRunLoopCommonModes形式处理self.networkingReachability
SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
(6)在后台检测self.networkReachability的网络状态,并使用SCNetworkReachabilityGetFlags函数返回产生的flag,注意此处flag表示的就是网络的状态
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags)) {
AFPostReachabilityStatusChange(flags, callback);
}
});
(7)AFPostReachabilityStatusChange当网络状态发生改变的时候使用该方法发送通知,通知用户目前的网络状态。通过userInfo[AFNetworkingReachabilityNotificationStatusItem]获取到相应的status
static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
// 使用AFNetworkReachabilityStatusForFlags函数将flags转化为status,提供给下面block使用
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
dispatch_async(dispatch_get_main_queue(), ^{
if (block) {
block(status);
}
// 对于用户,可以使用KVO来观察status的变化,随后用户可以根据传过来的userInfo[AFNetworkingReachabilityNotificationStatusItem]获取到相应的status
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo];
});
}