iOS-AFNetworking源码解析(四)

AFNetworkReachabilityManager

AFNetworkReachabilityManager是用来监测网络状态的类。设置状态改变回调方法,当网络状态改变时获得当前网络状态回调过来。

网络的状态值有以下四种: 

ypedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
    AFNetworkReachabilityStatusUnknown          = -1,// 未知
    AFNetworkReachabilityStatusNotReachable     = 0, // 不可用
    AFNetworkReachabilityStatusReachableViaWWAN = 1, // 无线广域网连接
    AFNetworkReachabilityStatusReachableViaWiFi = 2, // WiFi连接
};

AFNetworkReachabilityManager提供了五种初始化的方法。

 可以通过单例方法初始化

+ (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协议族的地址

+ (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地址来初始化

+ (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

- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
    self = [super init];
    if (!self) {
        return nil;
    }

    _networkReachability = CFRetain(reachability);
    self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;

    return self;
}

最后剩下一种方法就是可以根据特定的域来初始化

+ (instancetype)managerForDomain:(NSString *)domain {
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);

    AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
    
    CFRelease(reachability);

    return manager;
}

然后在初始化结束之后,我们需要设置网络状态改变的回调,在开启监听之后,会将网络状态回调给外部 

- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block {
    self.networkReachabilityStatusBlock = block;
}

 最后就是开启监听

- (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);
        }
    });
}

如果没有设置回调的话,也可以通过注册通知的方式,收到网络状态的变化

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里面的监听

- (void)stopMonitoring {
    if (!self.networkReachability) {
        return;
    }

    SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}

 

具体使用方法就如下:

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;
    }
}];

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值