到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf

到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf

Objective C 的 Block 是一个很实用的语法,特别是与GCD结合使用,可以很方便地实现并发、异步任务。但是,如果使用不当,Block 也会引起一些循环引用问题(retain cycle)—— Block 会 retain ‘self’,而 ‘self‘ 又 retain 了 Block。因为在 ObjC 中,直接调用一个实例变量,会被编译器处理成 ‘self->theVar’,’self’ 是一个 strong 类型的变量,引用计数会加 1,于是,self retains queue, queue retains block,block retains self。

解决 retain circle

Apple 官方的建议是,传进 Block 之前,把 ‘self’ 转换成 weak automatic 的变量,这样在 Block 中就不会出现对 self 的强引用。如果在 Block 执行完成之前,self 被释放了,weakSelf 也会变为 nil。

示例代码:

1
2
3
4
__weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [weakSelf doSomething];
});

clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外:

1
2
3
4
5
__weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [weakSelf doSomething];
    [weakSelf doOtherThing];
});

在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,于是,strongSelf 就派上用场了:

1
2
3
4
5
6
__weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong __typeof(self) strongSelf = weakSelf;
    [strongSelf doSomething];
    [strongSelf doOtherThing];
});

__strong 确保在 Block 内,strongSelf 不会被释放。

总结

  • 在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。
  • 如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。

参考

原文作者: lslin
原文链接: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/

时间: 2024-10-22 00:13:40

到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf的相关文章

疑惑:八卦掌趟泥步到底怎样走才正确?

--> 疑惑:八卦掌趟泥步到底怎样走才正确? 提交 我的留言 加载中 已留言 疑惑:八卦掌趟泥步到底怎样走才正确? 2016-06-08 佚名 功夫天下 功夫天下 功夫天下 微信号 kf_china 功能介绍 发扬中华武术精神,传承民族体育文化! 练八卦步先练直蹚泥步,练的蹚步平稳了再练走圈蹚泥步:然后学练站八卦桩,而后再学练掌.由开始蹚不出去步,练得趟出去而又稳健.八卦趟泥步利于气往下沉,主要练习重心的水平移动,它比形意的直线水平移动要难,因为它要走圈,人体的重心要在一个水平的圆圈上移动.八卦

初学Linux到底怎么学才是正确的学习方法?

首先从行业的角度分析Linux运维工程师这个职位,随着互联网行业不断发展壮大,越来越多复杂系统应运而生,为了保证系统稳定运行,必须要有足够多的Linux运维工程师.毕竟维护是软件生命周期中非常重要一个阶段,但是据统计目前国内的运维工程师人才是相对稀缺,故在近几年,运维工程师是一个热门职业. 对于2019年上半年,马哥教育做了一个考察,Linux运维的职位数量和平均薪资水平仍然持续了去年的强劲增幅,比很多开发岗位涨的都快.从研究机构的数据来看,Linux职位数量和工资水平涨幅均在IT行业的前五之列

(转)linux sudo 重定向,实现只有系统管理员才有权限操作的文件中写入信息

众所周知,使用 echo 并配合命令重定向是实现向文件中写入信息的快捷方式. 本文介绍如何将 echo 命令与 sudo 命令配合使用,实现向那些只有系统管理员才有权限操作的文件中写入信息. 比如要向 test.asc 文件中随便写入点内容,可以: $ echo "信息" > test.asc # 或者 $ echo "信息" >> test.asc 下面,如果将 test.asc 权限设置为只有 root 用户才有权限进行写操作: $ sudo

关于PCB布线的顺序到底是怎样才合理?

有人说先布好电源线和地线,让它们尽量靠近走,然后再考虑信号线:也有人说先布好关键的信号线,然后再走电源和地线:还有人说先布好电源线,再布信号线,地线最后布.到底怎么样才算好呢?或者说,一般应按照什么顺序? 从原理图时就仔细考虑了,原理图最好做成模块化的分立原理图,这样布的时候会轻松很多 先将复杂CPU 的引脚扇出到IC的外围. 推荐使用下面的顺序: 先摆好位置-->难点先布线-->其他布线-->电源线-->地线.

到底多大才算高并发?

一.什么是高并发 定义: 高并发(High Concurrency)是使用技术手段使系统可以并行处理很多请求. 关键指标: -响应时间(Response Time) -吞吐量(Throughput) -每秒查询率QPS(Query Per Second) -每秒事务处理量TPS(Transaction Per Second) -同时在线用户数量 关键指标的维度: -平均,如:小时平均.日平均.月平均 -Top百分数TP(Top Percentile),如:TP50.TP90.TP99.TP4个9

使用Reveal.app调试整个项目UI时间,增加LD指令 -Objc引起项目中多个静态库冲突问题

今天接触到一个新的UI调试工具教程如下: iOS真机UI调试利器——Reveal 引入增加-ObjC -framework Reveal指令后,发现项目出现多重静态库冲突问题, 首先介绍一个指令: -all_load选项,这会导致所有的类的方法都会被载入,不管“你的程序”有没有用到,所有的,包括系统的,方法会被载入.这个方法不仅会导致你的目标程序大小增大,而且往往容易引起一些冲突,而这些冲突往往你无法解决(常常出现在你链接的各种库中). 可以使用-force_load,这个你可以指定要载入所有方

斗地主你什么时候才会托管?(.NET中的托管于非托管)

文章部分引自<.NET4.0面向对象编程漫谈(基础篇)>第1章.NET面向对象编程基础(作者:金旭亮) 无意间看到一位四五岁左右小朋友在玩斗地主,总开始到结束,她一直都在使用“提示”(托管)出牌,你猜的没错,到最后她赢了. 那么你什么时候才会使用“托管”呢?“我想继续游戏,但是牌太烂了,索性托管吧或者我想玩,但是我会儿刚好有事需要处理” 实际上,我们在选择了.NET Framework平台后,就该选择使用什么语言了,但是每种语言都有自己的优缺点,例如,在非托管C/C++可对系统(Windows

Quartz与Spring整合进行热部署的实现(一)

先来几张实现图 任务管理页 新建任务管理.目前实现叫简单的需求...若各位同学要实现复杂的设计...quartz都有提供强大的支持.小弟目前的需求做到这已经够用了. 接下来.我们如何实现quartz的热部署编码呢? 小弟是利用spring整合quzrtz实现的.但是会产生两个小问题. 我们先看看quartz如何与spring整合 <bean name="quartzScheduler" class="org.springframework.scheduling.quar

分享一下自己ios开发笔记

// ********************** 判断数组元素是否为空 ********************** NSString *element = [array objectAtIndex:2]; if ((NSNull *)element == [NSNull null]) { } 今天做项目的时候就遇到,要判断数组元素是否为空,我的以下写法,都无效 if(!element) if([element length]>0) if(element== NULL) if(element