美文网首页iOS 程序员iOS Developer程序员
AFNetworking详解之AFNetworkReachabi

AFNetworking详解之AFNetworkReachabi

作者: my_杨哥 | 来源:发表于2017-04-11 17:06 被阅读363次
    AFNetworking

    AFNetworkReachabilityManager是用来监测网络状态,网络状态管理的类,他可以通过设置状态改变回调来获得当前网络状态。

    //网络的状态分四种
    typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
        AFNetworkReachabilityStatusUnknown          = -1,   //未知
        AFNetworkReachabilityStatusNotReachable     = 0,    //无网络
        AFNetworkReachabilityStatusReachableViaWWAN = 1,    //蜂窝网络
        AFNetworkReachabilityStatusReachableViaWiFi = 2,    //WiFi
    };
    

    一、属性

    公有属性(.h中的)

    // 当前网络的状态,就是枚举中的类型
    @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
    //当前网络是否可用(蜂窝网或WiFi)
    @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable;
    //当前网络是否是蜂窝网
    @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
    //当前网络是否是WiFi
    @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
    

    私有属性(.m中的)

    //用来保存创建测试连接返回的引用
    @property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability;
    //网络状态
    @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
    

    二、初始化

    AFNetworkReachabilityManager的初始化方法有5种
    1、单例初始化

    + (instancetype)sharedManager {
        static AFNetworkReachabilityManager *_sharedManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _sharedManager = [self manager];   //调用了+ manager方法
        });
    
        return _sharedManager;
    }
    

    2、在第一个单例方法中调用了此方法,通过默认的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
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_len = sizeof(address);
        address.sin_family = AF_INET;
    #endif
        return [self managerForAddress:&address];
    }
    

    3、在第二种方法里面又调用了此方法,通过传入一个socket地址来初始化。

    + (instancetype)managerForAddress:(const void *)address {
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
        AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
    
        CFRelease(reachability);
        
        return manager;
    }
    

    4、在第三种方法里面,又调用了第四种初始化方法,因为该方法的后缀里面有NS_DESIGNATED_INITIALIZER,所以最终都会调到它,这里就是做了初始化的工作,将起始的网络状态定为Unknown。

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

    5、这种方法就是可以根据特定的域来初始化。

    + (instancetype)managerForDomain:(NSString *)domain {
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
    
        AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
        
        CFRelease(reachability);
    
        return manager;
    }
    

    三、开始监听、停止监听

    1、开始监听方法

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

    2、停止监听方法

    - (void)stopMonitoring {
        if (!self.networkReachability) {
            return;
        }
    
        SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    }
    

    四、应用(demo)

    //监测网络状态的方法
    - (void)monitorReachabilityStatus
    {
        // 开始监测
        [[AFNetworkReachabilityManager sharedManager] startMonitoring];
        // 网络状态改变的回调
        [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status) {
                case AFNetworkReachabilityStatusReachableViaWWAN:
                    NSLog(@"蜂窝网络");
                    break;
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    NSLog(@"WIFI");
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                    NSLog(@"没有网络");
                    break;
                case AFNetworkReachabilityStatusUnknown:
                    NSLog(@"未知");
                    break;
                default:
                    break;
            }
        }];
    }
    

    相关文章

      网友评论

        本文标题:AFNetworking详解之AFNetworkReachabi

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