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