AFNetworkReachabilityManager 是AFNetworking框架里面 相對(duì)低耦合的一個(gè)部分,所以拿AFNetworkReachabilityManager開刀是個(gè)不錯(cuò)的算擇。
首先來看看AFNetworkReachability的功能:
'AFNetworkReachabilityManager' 監(jiān)視域名和WWAN和WiFi接口地址的Reachability。
然而網(wǎng)絡(luò)一般有兩種(蜂窩WWAN、WIFI)加上無網(wǎng)絡(luò)和未知錯(cuò)誤,一共四種網(wǎng)絡(luò)狀態(tài)
于是有了下面的枚舉類型:
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1,
AFNetworkReachabilityStatusNotReachable = 0,
AFNetworkReachabilityStatusReachableViaWWAN = 1,
AFNetworkReachabilityStatusReachableViaWiFi = 2,
};
通過這個(gè)需求我們引出了下面四個(gè)屬性:
/**
當(dāng)前網(wǎng)絡(luò)可用性的狀態(tài)
*/
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
/**
網(wǎng)絡(luò)當(dāng)前是否可用
*/
@property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable;
/**
WWAN網(wǎng)絡(luò)當(dāng)前是否可用
*/
@property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
/**
WiFI網(wǎng)絡(luò)當(dāng)前是否可用
*/
@property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
*注:BOOL類型要給出getter方法以添加 is 或者 have 前綴。
接下來是初始化方法,對(duì)于這種全局監(jiān)控的類來說,單例肯定是必要的。
/**
Returns the shared network reachability manager.
*/
+ (instancetype)sharedManager;
因?yàn)槲覀冞€要對(duì)特定的域名(domain)和網(wǎng)絡(luò)地址做監(jiān)控所以有了以下的初始化方法:
/**
Creates and returns a network reachability manager for the specified domain.
@param domain The domain used to evaluate network reachability.
@return An initialized network reachability manager, actively monitoring the specified domain.
*/
+ (instancetype)managerForDomain:(NSString *)domain;
/**
Creates and returns a network reachability manager for the socket address.
@param address The socket address (`sockaddr_in6`) used to evaluate network reachability.
@return An initialized network reachability manager, actively monitoring the specified socket address.
*/
+ (instancetype)managerForAddress:(const void *)address;
首先需要禁止用戶調(diào)用默認(rèn)的構(gòu)造方法init:
/**
* Initializes an instance of a network reachability manager
*
* @return nil as this method is unavailable
*/
- (nullable instancetype)init NS_UNAVAILABLE;
然而如果有多種初始化方法就需要一個(gè)總的初始化方法,基本所有的初始化方法都應(yīng)該調(diào)用該總初始化方法。于是有了下面的初始化方法:
/**
Initializes an instance of a network reachability manager from the specified reachability object.
@param reachability The reachability object to monitor.
@return An initialized network reachability manager, actively monitoring the specified reachability.
*/
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER;
*注:NS_DESIGNATED_INITIALIZER表明該初始化方法是總初始化方法,所有的初始化方法(包括子類的)都應(yīng)該代用該方法。
就如同C++,應(yīng)該有一個(gè)默認(rèn)構(gòu)造于是有了下面的默認(rèn)構(gòu)造方法:
/**
Creates and returns a network reachability manager with the default socket address.
@return An initialized network reachability manager, actively monitoring the default socket address.
*/
+ (instancetype)manager;
網(wǎng)絡(luò)變化了,需要通過回調(diào)告訴用戶,一般傳值有如下方法:
1.代理 2.通知 3.block 4.KVO
KVO會(huì)添加用戶操作所以pass,通知用block替代以減少用戶操作。block是用于一對(duì)一的,當(dāng)你設(shè)置了新的block的時(shí)候上一個(gè)block會(huì)失效,然而通知?jiǎng)t不同他是一對(duì)多的。
關(guān)于block我們有了以下方法:
/**
Sets a callback to be executed when the network availability of the `baseURL` host changes.
@param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`.
*/
- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block;
關(guān)于通知我們定義一下兩個(gè)NSString常量:一個(gè)用來表示通知的string,一個(gè)用來獲取通知userinfo中的信息
/**
Posted when network reachability changes.
This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability.
@warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (`Prefix.pch`).
*/
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem;
因?yàn)橐话闱闆r下是單例,無法銷毀,關(guān)閉監(jiān)聽的公開方法是必要的,既然有關(guān)閉監(jiān)聽的方法,開啟監(jiān)聽的方法也是必要的了。所以有了如下兩個(gè)方法:
/**
Starts monitoring for changes in network reachability status.
*/
- (void)startMonitoring;
/**
Stops monitoring for changes in network reachability status.
*/
- (void)stopMonitoring;
作為一個(gè)國(guó)際化的開發(fā)空間,反映出當(dāng)前網(wǎng)絡(luò)狀態(tài)的本地化文字也是必要的。所以有了如下方法:
/**
Returns a localized string representation of the current network reachability status.
*/
- (NSString *)localizedNetworkReachabilityStatusString;
當(dāng)然也有個(gè)C方法是轉(zhuǎn)換當(dāng)前的AFNetworkReachabilityStatus到字符穿的
FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status);
之所以用C方法并且用了FOUNDATION_EXPORT關(guān)鍵字,我猜測(cè)是為了進(jìn)一步簡(jiǎn)化用戶操作。而且字符串檢測(cè)速度很快直接用"=="就可以了。
=================================== 我是分割線 ===================================
來看看如何實(shí)現(xiàn)這些方法:
首先這個(gè)類是通過蘋果的SCNetworkReachabilityRef來實(shí)現(xiàn)功能的,所以要有一個(gè)SCNetworkReachabilityRef的實(shí)例變量。這里我們定一個(gè)SCNetworkReachabilityRef類型的屬性:
@property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability;
因?yàn)?h中networkReachabilityStatus是readonly,所以這里要把他變成readwrite
@property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
創(chuàng)建一個(gè)block,來存儲(chǔ)用戶的block
typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock;
接下來實(shí)現(xiàn)總初始化方法:
想法很簡(jiǎn)答,把參數(shù)傳過來的SCNetworkReachabilityRef給保存到實(shí)例變量中,并且初始化networkReachabilityStatus的數(shù)值。
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
self = [super init];
if (!self) {
return nil;
}
_networkReachability = CFRetain(reachability);
self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
return self;
}
*注:SCNetworkReachabilityRef是C層的結(jié)構(gòu)體指針,需要用CFRetain來持有。并且在不用的時(shí)候CFRelease釋放。
接下來實(shí)現(xiàn)另外兩個(gè)需要參數(shù)的工廠方法。這里所有的構(gòu)造方法最終都要調(diào)用總構(gòu)造,所以我們要把 domain 和 address 變成 SCNetworkReachabilityRef,然后傳遞給總構(gòu)造方法。
SCNetworkReachabilityRef 有三個(gè)構(gòu)造方法,這里用的是其中的兩個(gè)WithName 和 WithAddress。
+ (instancetype)managerForDomain:(NSString *)domain {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
+ (instancetype)managerForAddress:(const void *)address {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
CFRelease(reachability);
return manager;
}
*注:這里要CFRelease(reachability),因?yàn)樵诳倶?gòu)造方法中已經(jīng)CFRetain(reachability)了。
接下來實(shí)現(xiàn)的是默認(rèn)的工廠方法,看過《unix網(wǎng)絡(luò)編程》的人對(duì)這些代碼會(huì)比較熟悉。
首先需要一個(gè) sockaddr_in 的結(jié)構(gòu)體 來存儲(chǔ) socket 地址。
然后再用 bzero 把地址清空。
配置socket地址的基本屬性sin_family 和 sin_len。
當(dāng)然這里還需要根據(jù)系統(tǒng)來區(qū)分創(chuàng)建的是ipv6還是ipv4。
代碼如下:
+ (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];
}
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
self = [super init];
if (!self) {
return nil;
}
_networkReachability = CFRetain(reachability);
self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
return self;
}
最后來實(shí)現(xiàn)我們的單例方法,很簡(jiǎn)單的GCD調(diào)用:
+ (instancetype)sharedManager {
static AFNetworkReachabilityManager *_sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedManager = [self manager];
});
return _sharedManager;
}
當(dāng)然因?yàn)樾枰褂脩粽{(diào)用默認(rèn)的init方法所以做如下處理:
- (instancetype)init NS_UNAVAILABLE
{
return nil;
}
先別急著寫別的,先把dealloc寫了,以免忘記(如果忘了可能會(huì)造成大麻煩?。?。
dealloc方法需要做兩件事:
1.將實(shí)例變量該release的release掉,這里指的就是networkReachabilityStatus。當(dāng)然在release之前需要判斷是否為空,如果已經(jīng)釋放完了,再釋放會(huì)崩潰的。
2.停止監(jiān)聽,調(diào)用自己的stopMonitoring方法就好。
- (void)dealloc {
[self stopMonitoring];
if (_networkReachability != NULL) {
CFRelease(_networkReachability);
}
}
然后實(shí)現(xiàn)咱們之前設(shè)置的三個(gè)表示網(wǎng)絡(luò)狀態(tài)的getter
- (BOOL)isReachable {
return [self isReachableViaWWAN] || [self isReachableViaWiFi];
}
- (BOOL)isReachableViaWWAN {
return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN;
}
- (BOOL)isReachableViaWiFi {
return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi;
}
=================================== 我是分割線 ===================================
接下來就是重頭戲了startMonitoring。
這里挺復(fù)雜的我們先看源碼,一步一步來:
- (void)startMonitoring {
[self stopMonitoring];
if (!self.networkReachability) {
return;
}
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
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);
}
});
}
[self stopMonitoring];
在任何需要開始之前,先調(diào)用停止的方法。以免重復(fù)棄用(socket連接,動(dòng)畫方法等 都是如此)。
if (!self.networkReachability) {
return;
}
容錯(cuò)機(jī)制
Boolean
SCNetworkReachabilitySetCallback (
SCNetworkReachabilityRef target,
SCNetworkReachabilityCallBack __nullable callout,
SCNetworkReachabilityContext * __nullable context
) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);
這個(gè)是啟動(dòng)SCNetworkReachabilityRef
參數(shù)一 要啟動(dòng)的SCNetworkReachabilityRef
參數(shù)二 啟動(dòng)的 SCNetworkReachabilityRef變化的時(shí)候回調(diào)的SCNetworkReachabilityCallBack類型的函數(shù)指針
參數(shù)三 和參數(shù)二相相關(guān)的上下文
這里要講一下參數(shù)二
SCNetworkReachabilityCallBack 定義如下
typedef void (*SCNetworkReachabilityCallBack) (
SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags,
void * __nullable info
);
函數(shù)指針實(shí)際就是OC的block,大家完全可以把這個(gè)當(dāng)做一個(gè)block看待。我們像是定義一個(gè)block一樣來定義一個(gè)函數(shù)指針。
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
}
意思就是說當(dāng)
SCNetworkReachabilitySetCallback(::) 第一個(gè)參數(shù)啟動(dòng)的SCNetworkReachabilityRef發(fā)生變化的時(shí)候回直接調(diào)用這個(gè)函數(shù)。
這個(gè)函數(shù)中第一個(gè)參數(shù)(SCNetworkReachabilityRef __unused target)就是咱們啟動(dòng)的SCNetworkReachabilityRef。
第二個(gè)參數(shù)就是啟動(dòng)的SCNetworkReachabilityRef所變成的網(wǎng)絡(luò)狀態(tài),具體數(shù)值如下:
typedef CF_OPTIONS(uint32_t, SCNetworkReachabilityFlags) {
kSCNetworkReachabilityFlagsTransientConnection = 1<<0,
kSCNetworkReachabilityFlagsReachable = 1<<1,
kSCNetworkReachabilityFlagsConnectionRequired = 1<<2,
kSCNetworkReachabilityFlagsConnectionOnTraffic = 1<<3,
kSCNetworkReachabilityFlagsInterventionRequired = 1<<4,
kSCNetworkReachabilityFlagsConnectionOnDemand = 1<<5, // __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_0)
kSCNetworkReachabilityFlagsIsLocalAddress = 1<<16,
kSCNetworkReachabilityFlagsIsDirect = 1<<17,
#if TARGET_OS_IPHONE
kSCNetworkReachabilityFlagsIsWWAN = 1<<18,
#endif // TARGET_OS_IPHONE
kSCNetworkReachabilityFlagsConnectionAutomatic = kSCNetworkReachabilityFlagsConnectionOnTraffic
};
第三個(gè)參數(shù)就是咱們?cè)赟CNetworkReachabilitySetCallback中傳的第三個(gè)參數(shù)context中的一個(gè)info成員。
到這里
SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
這行算是解釋完了。
但是我們還需要一個(gè)context,所以上面的
SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
就是來創(chuàng)建這個(gè)的。
這個(gè)結(jié)構(gòu)體原型如下:
typedef struct {
CFIndex version;
void * __nullable info;
const void * __nonnull (* __nullable retain)(const void *info);
void (* __nullable release)(const void *info);
CFStringRef __nonnull (* __nullable copyDescription)(const void *info);
} SCNetworkReachabilityContext;
第一個(gè)是版本號(hào)。
第二個(gè)是在SCNetworkReachabilitySetCallback(::)傳給第二個(gè)函數(shù)指針的第二個(gè)參數(shù)info成員。
第三個(gè) 對(duì)于info的retain操作的函數(shù)指針
第四個(gè) 對(duì)于info的release操作的函數(shù)指針
第五個(gè) 描述
這里第一個(gè)填0就好,最后一個(gè)填NULL就好,中間還差三個(gè)。
這里我們要?jiǎng)?chuàng)建一個(gè)info,這個(gè)info是要最后傳遞給我們之前創(chuàng)建的C函數(shù)
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info)
中的。
而這個(gè)函數(shù)我們的目的是把第二個(gè)參數(shù)(網(wǎng)絡(luò)狀態(tài)),發(fā)送一個(gè)通知 并且 調(diào)用我們之前在.h中放出的
- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block;
block回調(diào)。
但是問題來了! 這個(gè)是C函數(shù),沒有self.的操作!我們要調(diào)用之前的block不能用self.networkReachabilityStatusBlock來獲取這個(gè)block,這時(shí)候info就排上用場(chǎng)了!我們要把這個(gè)self.networkReachabilityStatusBlock來放到info的位置,把這個(gè)self.networkReachabilityStatusBlock傳過來就好了。
創(chuàng)建info
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
回到4.
第二個(gè)參數(shù)通過第6步我們就得到了(AFNetworkReachabilityStatusBlock callback)
后面兩個(gè)參數(shù),既然知道了info是block,所以也可以的出來了。
static const void * AFNetworkReachabilityRetainCallback(const void *info) {
return Block_copy(info);
}
static void AFNetworkReachabilityReleaseCallback(const void *info) {
if (info) {
Block_release(info);
}
}
再回到第4部,把第7部的兩個(gè)函數(shù)指針給到第3個(gè)和第4個(gè)參數(shù)里面,至此我們的context終于完成了。
然后回到第3步我們創(chuàng)建的C函數(shù)
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
}
這里第3個(gè)參數(shù)就是一個(gè)block了。
我們?cè)賱?chuàng)建一個(gè)C函數(shù)用來發(fā)送通知和回調(diào)block的。
/**
* Queue a status change notification for the main thread.
*
* This is done to ensure that the notifications are received in the same order
* as they are sent. If notifications are sent directly, it is possible that
* a queued notification (for an earlier status condition) is processed after
* the later update, resulting in the listener being left in the wrong state.
*/
static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
dispatch_async(dispatch_get_main_queue(), ^{
if (block) {
block(status);
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo];
});
}
然后調(diào)用這個(gè)函數(shù)
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);
}
這里
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags)
是把系統(tǒng)的flag轉(zhuǎn)換成我們自己的AFNetworkReachabilityStatus
實(shí)現(xiàn)如下:
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;
}
然后這里把這個(gè)放到Runloop中啟動(dòng)
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
最后我們?cè)倩氐介_始,因?yàn)榈谝淮斡脩糸_始startMonitoring的時(shí)候,self.networkReachability的變化是不會(huì)計(jì)算在內(nèi)的,所以不會(huì)產(chǎn)生通知 和 回調(diào)block,所以這里我們要手動(dòng)調(diào)用一次。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
AFPostReachabilityStatusChange(flags, callback);
}
});
=================================== 我是分割線 ===================================
接下來就是收尾工作了:
stopMonitoring
- (void)stopMonitoring {
if (!self.networkReachability) {
return;
}
SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
本地化語言
NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil);
case AFNetworkReachabilityStatusReachableViaWWAN:
return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil);
case AFNetworkReachabilityStatusReachableViaWiFi:
return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil);
case AFNetworkReachabilityStatusUnknown:
default:
return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil);
}
}
KVO
#pragma mark - NSKeyValueObserving
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) {
return [NSSet setWithObject:@"networkReachabilityStatus"];
}
return [super keyPathsForValuesAffectingValueForKey:key];
}
如果networkReachabilityStatus發(fā)生變化則reachable 、reachableViaWWAN 、reachableViaWiFi調(diào)用自己的getter方法。
完結(jié)散花。
寫在最后,如果大家喜歡幫忙點(diǎn)下“關(guān)注”和“喜歡”,大家的鼓勵(lì)是我最大的動(dòng)力。