美文网首页
AFNetworking - AFNetworkReachabi

AFNetworking - AFNetworkReachabi

作者: ASkyWatcher | 来源:发表于2020-06-06 00:25 被阅读0次

AFNetworkReachabilityManager其实就是对SCNetworkReachability的封装,SCNetworkReachability就是是系统提供的网络监测的工具

我们先来看看SCNetworkReachability的一些网络状态枚举值

typedef CF_OPTIONS(uint32_t, SCNetworkReachabilityFlags) {
    kSCNetworkReachabilityFlagsTransientConnection      = 1<<0,
    kSCNetworkReachabilityFlagsReachable            = 1<<1,
    kSCNetworkReachabilityFlagsConnectionRequired       = 1<<2,
    kSCNetworkReachabilityFlagsConnectionOnTraffic      = 1<<3,
    kSCNetworkReachabilityFlagsInterventionRequired     = 1<<4,
    kSCNetworkReachabilityFlagsConnectionOnDemand
        API_AVAILABLE(macos(6.0),ios(3.0))      = 1<<5,
    kSCNetworkReachabilityFlagsIsLocalAddress       = 1<<16,
    kSCNetworkReachabilityFlagsIsDirect         = 1<<17,
    kSCNetworkReachabilityFlagsIsWWAN
        API_UNAVAILABLE(macos) API_AVAILABLE(ios(2.0))  = 1<<18,

    kSCNetworkReachabilityFlagsConnectionAutomatic  = kSCNetworkReachabilityFlagsConnectionOnTraffic
};

然后我们再看看AFNetworkReachabilityManager基于它封装的状态

NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) {
    switch (status) {
            //无网络
        case AFNetworkReachabilityStatusNotReachable:
            return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil);
            //手机网络
        case AFNetworkReachabilityStatusReachableViaWWAN:
            return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil);
            //wifi
        case AFNetworkReachabilityStatusReachableViaWiFi:
            return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil);
            //未知网络
        case AFNetworkReachabilityStatusUnknown:
        default:
            return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil);
    }
}

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);
    //网络可用的条件(有网络,不需要连接或者能够自动连接)
    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;
}

这样对比看下来,似乎好像一切开始变得清晰了。

我们监听网络的目的就是要对不同的网络状态做出相对应的回调处理,接下来就是设置网络状态变化的回调函数

static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusCallback block) {
    AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);//转化状态
    dispatch_async(dispatch_get_main_queue(), ^{
        AFNetworkReachabilityManager *manager = nil;
        if (block) {
            //网络状态改变回调执行
            manager = block(status);
        }
        //异步发送包含状态信息通知
        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
        NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
        [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:manager userInfo:userInfo];
    });
}

//用来设置SCNetworkReachabilitySetCallback中的状态回调block, 具体的回调内容设置在AFNetworkReachabilityStatusCallback里面
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusCallback)info);
}

以下两个是设置状态回调函数SCNetworkReachabilitySetCallback中SCNetworkReachabilityContext参数,该结构体中包含的两个对回调函数进行retain和release的参数

static const void * AFNetworkReachabilityRetainCallback(const void *info) {
    return Block_copy(info);
}

static void AFNetworkReachabilityReleaseCallback(const void *info) {
    if (info) {
        Block_release(info);
    }
}

关于对域名和socket的一些实例化方法,这里就不再赘述,我们直接看它的监听方法startMonitoring,在这里进行监听回调函数设置,然后加入到runloop

- (void)startMonitoring {
    //先结束当前的监听
    [self stopMonitoring];

    if (!self.networkReachability) {
        return;
    }

    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusCallback callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;//防止self被释放,后面执行block更安全

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }
        
        return strongSelf;
    };
    /* 设置回调函数   Boolean
    SCNetworkReachabilitySetCallback        (
                            SCNetworkReachabilityRef            target,
                            SCNetworkReachabilityCallBack    __nullable    callout,
                            SCNetworkReachabilityContext    * __nullable    context
                            )                API_AVAILABLE(macos(10.3), ios(2.0));
     */
    //上下文
    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);
        }
    });
}

- (void)stopMonitoring {
    if (!self.networkReachability) {
        return;
    }
    //取消运行循环
    SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}

相关文章

网友评论

      本文标题:AFNetworking - AFNetworkReachabi

      本文链接:https://www.haomeiwen.com/subject/xohazhtx.html