说说Strong-Weak Dance 的理解

2017-12-07  本文已影响0人  devVector

why

开发工程中为什么要用Strong-Weak Dance,明显的retain release操作, 增加了运行时开销,这么做的好处是什么?

典型案例

AFNetworkReachabilityManager.m文件中, 这里摘了几个重要函数 做简要分析

- (void)startMonitoring {
    [self stopMonitoring];

    if (!self.networkReachability) {
        return;
    }
   //创建了callback
   __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;

//这里设想一下, 如果是strongSelf 作为参数去调用别的函数,且函数规定参数必须非空,否则abort(), 这里需要怎么做
        if (strongSelf.networkReachabilityStatusBlock) {//判断非空,既然是对networkReachabilityStatusBlock判空, 同时也对 strongSelf进行了判空
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };*

//SCNetworkReachability 的回调block
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);

//在global_queue中使用了callback
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
}

static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);
}
static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
    AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
//又异步到主队列,在主队列中使用了callback
    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];
    });
}

代码中的一些需要注意的点

  1. self 在多个线程中访问
  2. strongSelf 后有一个判空操作 if (strongSelf.networkReachabilityStatusBlock)
  3. networkReachabilityStatusBlock 执行时必须非空

weakSelf的意义

打破 self self.networkReachability callback 之间的循环引用

这里strongSelf 的意义

如果不用strongSelf强引用, 在多线程环境中,会存在这样的场景: if (strongSelf.networkReachabilityStatusBlock) 执行完成后线程被挂起(且结果为true), 如果不强引用会有这样的情况发生:挂起前self 引用计数>0;挂起期间, 其他的线程对self 进行了release 操作,导致self 被释放;线程回复后 执行到strongSelf.networkReachabilityStatusBlock(status); 导致crash

精髓

weak strong dance 的精髓在于 多线程中确保 block在执行过程中使用 weakSelf的期间,weakSelf 不会被释放。
多线程访问的对象的弱引用在需要判空时, 一定要先强引用, 再判空强引用非空。

失败案例

//只起到弱引用, 需要加上注释掉的部分代码,strongSelf 只是拿到了weakSelf retain 之后的value, 不能确保strongSelf 非空

__weak MyViewController *weakSelf = self;
self.completion= ^() {
    __strong __typeof(weakSelf) strongSelf = weakSelf;
    [property removeObserver: strongSelf forKeyPath:@"pathName"];
};

修正后代码:

__weak MyViewController *weakSelf = self;
self.completion= ^() {
    __strong __typeof(weakSelf) strongSelf = weakSelf;
    if (nil == strongSelf) {
        return;
    }
    [property removeObserver: strongSelf forKeyPath:@"pathName"];
};
上一篇 下一篇

猜你喜欢

热点阅读