23·iOS 面试题·描述一个 retain cycle 例子
0

前言

这个题目就比较简单了,在平时开发中,总是会遇到循环引用的问题,这里我们先聊一下为什么会出现循环引用,然后再列举 Block 和 Delegate 是如何出现循环引用以及如何避免。

循环引用的原因

首先我们知道 Objective-C 是利用引用计数机制来进行内存管理而不是垃圾回收,引用计数机制其中一个缺点就是不能自动解决循环引用的问题,需要我们手动处理。

简单来说,每个对象都有一个与之对应的引用计数值,只有当引用计数值为 0 的时候,该对象才会被系统回收。当对象 A 强引用对象 B,对象 B 又强引用了对象 A,这样子对象 A 和 对象 B,它们的引用计数值都不会为 0,即它们都不会被系统回收,这里就出现了循环引用了。

Delegate 出现循环引用例子 & 解决方案

例子:

Person:
@property (nonatomic, strong) id delegate;

self.person = [Person new];
self.person.delegate = self;

// self 强引用了 person
// self.person.delegate = self; -> person 强引用了 self
// 这里就出现了循环引用

解决方案:

Person:
@property (nonatomic, weak) id delegate;

self.person = [Person new];
self.person.delegate = self;

// self 强引用了 person
// self.person.delegate = self; -> person 弱引用了 self
// 这里不会出现循环引用

Block 出现循环引用例子 & 解决方案

@property (nonatomic, copy) void (^myBlock)();

self.myBlock = ^{
        self;
});
// self 强引用了 myBlock
// myBlock 截获了self -> 即 myBlock 强引用了 self
// 这里就出现了循环引用

解决方案:

@property (nonatomic, copy) void (^myBlock)();

__weak typeof(self)weakSelf = self;
self.myBlock = ^{
        weakSelf;
});
// self 强引用了 myBlock
// myBlock 截获了 weakSelf -> 即 myBlock 弱引用了 self
// 这里不会出现循环引用

Block 还有种特殊情况,在执行 Block 时候,self 可能会被释放了,所以我们需要在 Block 内部对 self 进行强引用,确保在执行 Block 期间,self 不会被释放:

@property (nonatomic, copy) void (^myBlock)();

__weak typeof(self)weakSelf = self;
self.myBlock = ^{
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        strongSelf;
});

总结

只要明白了对象之间持有关系,还是比较容易避免循环引用的问题。

学为好人。

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!