AFNetworking詳解之AFNetworkReachabilityManager(網(wǎng)絡(luò)狀態(tài))

AFNetworking

AFNetworkReachabilityManager是用來監(jiān)測(cè)網(wǎng)絡(luò)狀態(tài),網(wǎng)絡(luò)狀態(tài)管理的類,他可以通過設(shè)置狀態(tài)改變回調(diào)來獲得當(dāng)前網(wǎng)絡(luò)狀態(tài)。

//網(wǎng)絡(luò)的狀態(tài)分四種
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
    AFNetworkReachabilityStatusUnknown          = -1,   //未知
    AFNetworkReachabilityStatusNotReachable     = 0,    //無(wú)網(wǎng)絡(luò)
    AFNetworkReachabilityStatusReachableViaWWAN = 1,    //蜂窩網(wǎng)絡(luò)
    AFNetworkReachabilityStatusReachableViaWiFi = 2,    //WiFi
};

一、屬性

公有屬性(.h中的)

// 當(dāng)前網(wǎng)絡(luò)的狀態(tài),就是枚舉中的類型
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
//當(dāng)前網(wǎng)絡(luò)是否可用(蜂窩網(wǎng)或WiFi)
@property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable;
//當(dāng)前網(wǎng)絡(luò)是否是蜂窩網(wǎng)
@property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
//當(dāng)前網(wǎng)絡(luò)是否是WiFi
@property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;

私有屬性(.m中的)

//用來保存創(chuàng)建測(cè)試連接返回的引用
@property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability;
//網(wǎng)絡(luò)狀態(tài)
@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];   //調(diào)用了+ manager方法
    });

    return _sharedManager;
}

2、在第一個(gè)單例方法中調(diào)用了此方法,通過默認(rèn)的socket地址初始化,返回一個(gè)manager對(duì)象,sin_family表示協(xié)議族,AF_INET表示TCP/IP協(xié)議族的地址。

+ (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、在第二種方法里面又調(diào)用了此方法,通過傳入一個(gè)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、在第三種方法里面,又調(diào)用了第四種初始化方法,因?yàn)樵摲椒ǖ暮缶Y里面有NS_DESIGNATED_INITIALIZER,所以最終都會(huì)調(diào)到它,這里就是做了初始化的工作,將起始的網(wǎng)絡(luò)狀態(tài)定為Unknown。

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

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

    return self;
}

5、這種方法就是可以根據(jù)特定的域來初始化。

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

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

    return manager;
}

三、開始監(jiān)聽、停止監(jiān)聽

1、開始監(jiān)聽方法

- (void)startMonitoring {
    [self stopMonitoring];

    if (!self.networkReachability) {
        return;
    }
    // 收到callback調(diào)用后,將status通過networkReachabilityStatusBlock回調(diào)出去
    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };
    // 聲明SCNetworkReachabilityContext結(jié)構(gòu)體
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    // 設(shè)置回調(diào)
    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
    // 加到Main runloop里面對(duì)其進(jìn)行監(jiān)測(cè)
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    // 獲取當(dāng)前的網(wǎng)絡(luò)狀態(tài),調(diào)用callback
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
}

2、停止監(jiān)聽方法

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

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

四、應(yīng)用(demo)

//監(jiān)測(cè)網(wǎng)絡(luò)狀態(tài)的方法
- (void)monitorReachabilityStatus
{
    // 開始監(jiān)測(cè)
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
    // 網(wǎng)絡(luò)狀態(tài)改變的回調(diào)
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"蜂窩網(wǎng)絡(luò)");
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"WIFI");
                break;
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"沒有網(wǎng)絡(luò)");
                break;
            case AFNetworkReachabilityStatusUnknown:
                NSLog(@"未知");
                break;
            default:
                break;
        }
    }];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容