iOS内存管理 —— 散列表和弱引用表

iOS内存管理 —— 散列表和弱引用表

1. 散列表

散列表的本质是哈希表。散列表在手机上有8张,在模拟器或者其他设备上为64张。散列表里面有引用计数表弱引用表。其中锁用来保证线程安全,引用计数表是用来存超过最大个数的引用计数的,弱引用表则是用来储存__weak修饰的变量和weak修饰的属性等。如果在整个系统中只有一张散列表,那么在使用过程中开表和关表,为了保证线程安全就要开锁和解锁,如果所有对象挤在一个表里,就会导致性能等消耗。多张表还可以及时回收相关内存。

2. 弱引用表

这里的打印结果是什么呢?运行后发现是12,按道理来说,这里的引用计数应该是 11, 那么为什么weakObjc的引用计数是2呢?
在这里插入图片描述
在这里插入图片描述
alloc的时候_class_createInstanceFromZone调用objc->initIsa会进行引用计数赋值为1的操作。而weak修饰的就不会进行引用计数+1的操作,所以objc引用计数为1。
在这里插入图片描述
__weak处打下断点,连续step into后发现进入了objc_initWeak
在这里插入图片描述
搜索objc_initWeak
在这里插入图片描述
接下来看storeWeak。这里如果是第一次进来的话,就会走到haveNew里面。
在这里插入图片描述
往下走会调用weak_register_no_lock进行注册。
在这里插入图片描述
来到weak_register_no_lock,看到这里先是做了状态的判断,然后判断弱引用表是否存在,存在则append进去,否则就新建一个插入。
在这里插入图片描述
如果有关于这个对象的弱引用表,则进行append_referrer往这个表里添加,并且判断是否进行四分之三扩容。
在这里插入图片描述
没有的话就进行对象和指针地址的绑定,然后做相应的扩容以及插入操作。
在这里插入图片描述
在这里插入图片描述
所以这里的过程是

  • 得到散列表的弱引用表
  • 创建一个 weak_entry_T
  • referent加入到weak_table的数组inline_referrers
  • weak_table扩容一下
  • new_entry加入到weak_table

在打印的weakObjc引用计数的地方打下断点后运行,发现调用objc_loadWeakRetained
在这里插入图片描述
接下来到objc_loadWeakRetained里面。这里obj是临时变量,而*location则是外面的object对象,这里将object对象赋值给obj,这里看到运行到这里的时候retainCount还是1。
在这里插入图片描述
接下来走到rootTryRetain
在这里插入图片描述
这里调用了rootRetain,这里会进行retain操作,就会对引用计数进行+1处理。
在这里插入图片描述
出来后看到,这里的引用计数变成了2。所以这里的weakObj的引用计数为2。
在这里插入图片描述
objc_loadWeakRetained里面的obj 和 result都是临时变量,所以出了作用域之后就会被释放掉,就会进行release,所以打印两次retainCount不会变为3。
在这里插入图片描述

3. 面试题

这样使用timer是否有问题呢?这里会有self-> self.timer -> self 的循环引用问题。这里timer是无法进行弱引用的否则会奔溃,那么该怎么处理呢?这里用weakself也是没有效果的,因为runloop会强持有target。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里可以用另外一个带有block的api,这个api不会对self进行强持有。
在这里插入图片描述
这里还可以在viewWillDisappear的时候对timer进行处理,这里有个问题就是无论pop还是push都会对timer进行处理。
在这里插入图片描述
调用这个api的话,pop的话就会销毁timer,而push的话就不会有影响。
在这里插入图片描述
这里还可以用中介者模式来避免循环引用,这里当发现外部objc释放之后,就会在fireHomeWapper自动释放timer。
在这里插入图片描述
外部调用:
在这里插入图片描述
也可以用虚基类来进行快速或者慢速消息转发。这样就不对self强持有,而是对self.proxy进行强持有。proxy强持有释放与否由self.timer控制的,self.timer释放则是由vc能控制的,只要vc能释放,那么timerproxy就能正常释放。
在这里插入图片描述
在这里插入图片描述

外部调用:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值