转载自:http://sherlockyao.com/blog/2015/08/08/weakself-and-strongself-in-blocks/

现在我们用 Objective-C 写代码时已经越来越多地用到了block,相比delegate的回调方式,block更直观易用。相信每个使用过block的人都遇到过block中使用self时需要weakself的情况,以下就是非常典型的一段代码:

1
2
3
4
5
__weak __typeof(self)weakSelf = self;
[self.context performBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomething];
}];

对于小白的我一般越到这种情况就是直接拷贝上面这个模板到需要的代码中去,而不知个中原委。但作为一个合格的程序员,是需要完完全全明白自己写的每一行代码是在做什么的,所以现在就简单说明一下这个 WeakSelf 和 StrongSelf 到底是什么。首先看下面这段代码:

1
2
3
[UIView animateWithDuration:0.2 animations:^{
self.myView.alpha = 1.0;
}];

在ARC环境下的,每个block在创建时,编译器会对里面用到的所有对象自动增加一个reference count,然后当block执行完毕时,再释放这些reference。针对上面的代码,在animations block执行期间,self(假设这里的self是个view controller)的引用数会被加1,执行完后再次减1。但这种情况下为什么我们一般不会去weakify self呢?因为这个block的生命周期是明确可知的,在这个block执行期间当前的view controller一般是不会被销毁的,所以不存在什么风险。现在我们看下面这个例子:

1
2
3
4
5
NSBlockOperation *op = [[[NSBlockOperation alloc] init] autorelease];
[op addExecutionBlock:^ {
[self doSomething];
[self doMoreThing];
}];

在这种情况下,我们并不知道这个execution block什么时候会执行完毕,所以很有可能发生的情况是,我在block还没执行完毕时就想销毁当前对象(比方说用户关闭了当前页面),这时就会因为block还对self有一个reference而没有立即销毁,这会引起很多问题,比方说你写在- (void)dealloc {}中的代码并不能马上得到执行。所以为了避免这种情况,我们会在block前加上__weak __typeof(self)weakSelf = self;的定义来使block对self获取一个弱引用(也就是refrence count不会加1)。

那block中的StrongSelf又是做什么的呢?还是上面的例子,当你加了WeakSelf后,block中的self随时都会有被释放的可能,所以会出现一种情况,在调用doSomething的时候self还存在,在doMoreThing的时候self就变成nil了,所以为了避免这种情况发生,我们会重新strongify self。一般情况下,我们都建议这么做,这没什么风险,除非你不关心self在执行过程中变成nil,或者你确定它不会变成nil(比方说所以block都在main thread执行)。

好了,简要的说明到此结束,想要详细了解的可以自行google,这类文章很多。前面代码中的WeakSelf、StrongSelf转换看起来很冗长,不利于阅读代码,下面介绍一个超好用的宏定义代码,它是这个开源库的一部分:libextobjc。把它加入到项目中后,就可以用以下如此简洁的格式来完成转换啦:

1
2
3
4
5
6
7
#import "EXTScope.h"

@weakify(self)
[self.context performBlock:^{
@strongify(self)
[self doSomething];
}];

WeakSelf和StrongSelf的更多相关文章

  1. 深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用(下)

    深入研究Block捕获外部变量和__block实现原理 EOCNetworkFetcher.h typedef void (^EOCNetworkFetcherCompletionHandler)(N ...

  2. 深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用(上)

    深入研究Block捕获外部变量和__block实现原理 前言 在上篇中,仔细分析了一下Block的实现原理以及__block捕获外部变量的原理.然而实际使用Block过程中,还是会遇到一些问题,比如R ...

  3. [HMLY]10.深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用

    前言 在上篇中,仔细分析了一下Block的实现原理以及__block捕获外部变量的原理.然而实际使用Block过程中,还是会遇到一些问题,比如Retain Circle的问题. 目录 1.Retain ...

  4. weakSelf 和 strongSelf

    最近在看SDWebImage源码,碰到一些比较绕的问题,理解了很久,然后在网上查了些的资料,才算是有了一些理解.在此记录一下. 源码如下: block会copy要在block中使用的实变量,而copy ...

  5. weakSelf 和 strongSelf的区别和用处

    block会copy要在block中使用的实变量,而copy会是变量的retainCount + 1,如若在不注意很容易造成循环引用.而所谓的循环引用的本质就是,两个对象相互引用,从而造成对象不能正常 ...

  6. weakSelf 运用 strongSelf来解决block的循环引用

    SDWebImage 中有一段源码: #if SD_UIKIT Class UIApplicationClass = NSClassFromString(@"UIApplication&qu ...

  7. 关于iOS Block当中为什么要用weakSelf和strongSelf的思考

    场景:当你在某个界面请求网络数据的时候,用户不愿意等待点击了返回按钮,此时在Block当中用如下的方式使用weakSelf的话,有可能会奔溃(因为在并发编程的情况下,虽然在if判断的时候weaksel ...

  8. @weakify, @strongify ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

  9. ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

随机推荐

  1. Varnish && Varnish Cache

    1 1 1 Varnish https://www.varnish-cache.org/intro/index.html#intro Introduction to Varnish The basic ...

  2. find排除目录

    在linux find 进行查找的时候,有时候需要忽略某些目录不查找,可以使用 -prune 参数来进行过滤,但必须要注意要忽略的路径参数必须紧跟着搜索的路径之后,否则该参数无法起作用. 命令语法: ...

  3. git 忽略已跟踪的文件

    对于未跟踪的文件,可以编辑.gitignore文件进行忽略. 对于已跟踪的文件,编辑.gitignore文件不会起作用,它只针对未被跟踪的文件,也就是你先设置规则,然后添加的新文件符合这些规则的就会被 ...

  4. C语言隐式强制类型转换

    今天又被精度问题困扰,把最基本的东西忘了. int n = 5; int cnt = 5.5; double sum = (n-cnt);  运算完后sum是 -0.5.不知道什么时候n转换成doub ...

  5. string的数值转换

    to_string(val); //数值val的string表示 stoi (s, p, b); stol (s, p, b); stoul (s, p, b); stoll (s, p, b); s ...

  6. Django: 之用户注册、缓存和静态网页

    Django 用户注册系统 Django 的源码中已经有登录,退出,重设密码等相关的视图函数,在下面这个app中 django.contrib.auth 可以点击对应的版本查看相关源代码:1.9  1 ...

  7. Mac下截图快捷键

    Cmd+Shift+3:全屏截图:截取整个屏幕,保存截图至桌面文件夹.Cmd+Shift+4:区域截图:鼠标光标变成带坐标的小十字,通过拖拽截取特定区域,保存截图至桌面文件夹.Cmd+Shift+4 ...

  8. H5调用本地摄像头

    <!DOCTYPE html><html><head lang="en"><meta charset="UTF-8"& ...

  9. Immutable 详解及 React 中实践

    本文转自:https://github.com/camsong/blog/issues/3 Shared mutable state is the root of all evil(共享的可变状态是万 ...

  10. intent.putExtra()方法参数详解

    [开篇骂几句:fuck]1.扯淡intent.putExtra()怎么使用?2.胡说intent.putExtra(); [扯淡:其实你在问它怎么用的时候,你要明白,你知道不知道这是个什么东东,有必要 ...