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