OC中的弱引用容器

PS: 本来打算三月就完成这两篇博客,但是因为换工作比较忙,一直到现在才有时间更新。

背景

OC 中常见的容器都是强引用的,比如NSArray,NSDictary,NSSet等,但是我们偶尔也需要一个弱引用的容器。
目前我了解到的比较成熟并且容易实现的方法有两个:

实现方法

方法1:使用桥接类,weak修饰

假如容器是: NSMutableArray

目标类是: Person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// .h文件
// 定义桥接类
@interface PersonBridge :NSObject
/* 在桥接类中声明一个weak修饰的属性 */
@property (weak , nonatomic) Person *weakPerson;

@end

// .m文件
@implementation PersonBridge


@end


// 使用方法,假如需要把person1,和person2添加到数组中,就可以如下操作

PersonBridge *personBridge1 = [[PersonBridge alloc] init];
personBridge.weakPerson = person1;

PersonBridge *personBridge2 = [[PersonBridge alloc] init];
personBridge.weakPerson = person2;

[self.mArray addObject:personBridge1];
[self.mArray addObject:personBridge2];

每个需要加入数组中的Person,都通过PersonBridge加入到数组中,让数组强引用PersonBridge对象,PersonBridge对象弱引用Person对象
这样假如person1销毁时,不会因为有数组引用而无法销毁,销毁后,PersonBridge对象的weakPerson属性被自动置为nil,不会造成野指针问题

方法2:使用系统提供的弱引用容器类型 NSPointerArray

对于这个弱引用的需求,苹果其实早就提供了比较优雅的解决方案

1
2
3
4
5
6
7
8
9
// 创建弱引用数组
NSPointerArray *weakArray = [NSPointerArray weakObjectsPointerArray];

NSObject *obj = [[NSObject alloc] init];
// 添加到弱引用数组中
[weakArray addPointer:(__bridge void * _Nullable)(obj)];

// 清空数组中的NULL Value
[weakArray compact];

NSPointerArray类似的类还有NSMapTable,NSHashTable

其实还有第三种实现方法,就是用NSValue包装,但是有瑕疵,不知道是不是我用的姿势不对

1
2
3
4
5
6
7
8
9
10
11
12
// 需要包装的对象
NSObject *tempObj = [[NSObject alloc] init];

// 使用NSValue进行包装
NSValue *nonRetainValue = [NSValue valueWithNonretainedObject:tempObj];

// 用时直接使用属性取
NSObject *obj = (NSObject *)[nonRetainValue nonretainedObjectValue];

// 但是测试时发现,如果tempObj 被销毁,从nonRetainValue取出的值不是nil,也不是NULL,
// 所以不知道如何判空,这是我疑惑的地方,如果不能判空,那就很容易造成crash
// 如果有高人知晓,还望告知正确用法