AFNetworkReachabilityManager
管理网络的可达性,在某个网络请求失败的时候,它可以给出具体的原因;当网络连接建立后,它可以触发指定的网络操作。
property
Initialization
+ sharedManager + manager + managerForDomain: + managerForAddress: – initWithReachability:
sharedManager是单例的,并且是采用GCD中的dispatch_once实现的:
+ (instancetype)sharedManager { static AFNetworkReachabilityManager *_sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedManager = [self manager]; }); return _sharedManager; }
dispatch_once:
此函数接收类型为dispatch_once_t的特殊参数,还有一个块参数。对于onceToken标记,该函数保证相关的块必会执行且执行一次。此操作是线程安全的。注意:对于只执行一次的块来说,传入函数的标记参数必须完全相同,因此,开发时需要将标记变量声明为static或全局作用域内。
使用这种方式设计单例,开发者无需考虑加锁问题或线程同步问题,所有问题都在GCD底层处理。
dispatch_once采用“原子访问” 来查询标记,判断代码是否执行过。
参考:blog
manager创建实例对象
+ (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;//ipv6类型的地址结构体 bzero(&address, sizeof(address)); address.sin6_len = sizeof(address); address.sin6_family = AF_INET6; #else struct sockaddr_in address;//ipv4类型的地址结构体 bzero(&address, sizeof(address)); address.sin_len = sizeof(address); address.sin_family = AF_INET; #endif return [self managerForAddress:&address]; }
这个方法实际上做了一些socket通信时变量初始化的一些操作:指定地址类型、协议蔟。
然后调用managerForAddress:方法创建:
+ (instancetype)managerForAddress:(const void *)address { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; CFRelease(reachability); return manager; }
reachability是一个SCNetworkReachabilityRef类型的结构体,其中address参数是需要监听的地址。
然后调用initWithReachability来创建:
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; if (!self) { return nil; } _networkReachability = CFRetain(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; return self; }
reachability状态初始化为unknown.
由于SCNetworkReachabilityRef是一个Core Foundation框架中的对象,使用CFRetain进行内存管理。
managerForAddress通过传入一个sockaddr类型的ip地址来初始化;因为调用了initWithReachability,所以需要CFRelease一下。
managerForDomain通过传入一个域名类型的ip地址来初始化,如“www.baidu.com”;同样因为调用了initWithReachability,所以需要CFRelease一下。
[to be continued...]