AFNetwork 3.0 源码解读(二)网络情况监听

继续上篇,前面一节介绍了AFNetwork3.0的一些变化。。这篇文章主要是介绍网络情况监听,在AFNetwork框架中用来监听的类是AFNetworkReachabilityManager。所以我们对AFNetworkReachabilityManager进行一个了解。

作者对于Reachability的建议是
  • 在开发网络请求中,不应该一开始就是用Reachability来判断网络请求是否应该发送,你应该尝试的发送它
  • 你可以使用Reachability,来决定一个request是否重新自动请求。尽管重新发送它还是可能会失败,但是Reachability监听到网络是可用的情况下发送,不失为一个好的时机
  • 使用reachability你可以更优雅的来处理网络失败的原因,你可以告诉用户网络中断了而不是机械化的告诉用户详细的错误原因。比如“请求超时”等。

AFNetworkReachabilityManager继承至NSObject用来监听域、 无线广域网路(Wireless Wide Area Network)和Wifi是否正常连接。

Ps:无线广域网路(Wireless Wide Area Network) 就是目前我们使用的手机网络

组成:
属性(property)

    AFNetworkReachabilityStatusUnknown          = - 1 ,  /// 未知网络
    AFNetworkReachabilityStatusNotReachable     = 0 ,   /// 无法连接到网络
    AFNetworkReachabilityStatusReachableViaWWAN = 1 ,   ///  无线广域网路
    AFNetworkReachabilityStatusReachableViaWiFi = 2,   /// WiFi情况

类方法(class Methods)
+ (instancetype)managerForAddress:(const struct sockaddr_in *) address
创建并返回监听一个socket地址的监听器
address:用来被监听的socket地址

+ (instancetype)managerForDomain:(NSString *) domain
创建并返回一个监听指定域名的监听器
domain:用来被监听的域名地址

+ (instancetype)sharedManager
返回一个单例的网络监听器


对象方法(Instance Methods)

- (instancetype)initWithReachability:(SCNetworkReachabilityRef) reachability
根据一个特定的 SCNetworkReachabilityRef对象初始化一个监听器

- (NSString *)localizedNetworkReachabilityStatusString
返回本地网络是否可达的状态字符串

- (void)setReachabilityStatusChangeBlock:(void ( ^ ) ( AFNetworkReachabilityStatus status )) block
设置 网络变化时的block,可以根据staus来自定义相关操作

- (void)startMonitoring
开始监听网络情况
- (void)stopMonitoring
结束监听
—————————————————————————————— 伟大的分割线 ———————————————————————————————————————————————
好了,以上是简单的介绍。下面开始扒一扒里面的代码。
AFNetworkReachabilityManager能够检测网络情况是因为包含了 <SystemConfiguration/SCNetworkReachability.h> 中SCNetworkReachability工具,


/// sharedManager、manager 最后都是调用下面的方法返回一个持有 SCNetworkReachability对象的 AFNetworkReachabilityManager 其中

+ ( instancetype )managerForAddress:( const void *)address {
   
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress ( kCFAllocatorDefault , ( const struct sockaddr *)address);
    AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
    return manager;
}

SCNetworkReachabilityRef SCNetworkReachabilityCreateWithAddress (     // 根据传入的地址创建网络连接 引用
   CFAllocatorRef allocator,                   // 可以为NULL或kCFAllocatorDefault
   const struct sockaddr *address             // 需要测试连接的IP地址
);
根据传入的地址测试连接,第一个参数可以为NULL或kCFAllocatorDefault,第二个参数为需要测试连接的IP地址,当为0.0.0.0时则可以查询本机的网络连接状态。同时返回一个引用必须在用完后释放。

/// 主要的方法
- ( void )startMonitoring {

    [self stopMonitoring];
    if (! self . networkReachability ) {
       
return ;
    }
    __weak __typeof ( self )weakSelf = self ;
      // 设置回调的block
    AFNetworkReachabilityStatusBlock callback = ^( AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        strongSelf. networkReachabilityStatus = status;
       
if (strongSelf. networkReachabilityStatusBlock ) {
            strongSelf.
networkReachabilityStatusBlock (status);
        }
    };

    id networkReachability = self . networkReachability ;
          /// 包含指定的数据和回调
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
     /// 设置一个用户指定的 SCNetworkReachabilityRef 对象,当网络发生变化时调用的block
    SCNetworkReachabilitySetCallback (( __bridge SCNetworkReachabilityRef )networkReachability, AFNetworkReachabilityCallback , &context);
     /// 将指定的 SCNetworkReachabilityRef 加入到运行循环中
    SCNetworkReachabilityScheduleWithRunLoop (( __bridge SCNetworkReachabilityRef )networkReachability, CFRunLoopGetMain (), kCFRunLoopCommonModes );

   
dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_BACKGROUND , 0 ),^{
       
SCNetworkReachabilityFlags flags;
       
if ( SCNetworkReachabilityGetFlags (( __bridge SCNetworkReachabilityRef )networkReachability, &flags)) {
           
AFPostReachabilityStatusChange (flags, callback);
           }
    });
}



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;

Boolean
SCNetworkReachabilitySetCallback (
SCNetworkReachabilityRef target,
SCNetworkReachabilityCallBack __nullable callout,
SCNetworkReachabilityContext * __nullable context
) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);

Boolean
SCNetworkReachabilityScheduleWithRunLoop (
SCNetworkReachabilityRef target,
CFRunLoopRef runLoop,
CFStringRef runLoopMode
) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);

Boolean
SCNetworkReachabilityGetFlags (
SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags *flags
) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);

SCNetworkReachability 编程接口支持同步和异步两种模式。 在同步模式中,可以通过调用SCNetworkReachabilityGetFlag函数来获得可达性状态;在异步模式中,可以调度SCNetworkReachability对象到客户端对象线程的运行循环上,客户端实现一个回调函数来接收通知,当远程主机改变可达性状态,回调则可响应。 

猜你喜欢

转载自blog.csdn.net/yuwuchaio/article/details/50419232