AFNetworking源代码之路

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...]

猜你喜欢

转载自blog.csdn.net/wing1010/article/details/80032522