iOS 实现弱引用数组的几种方法

作者 Tsui YuenHong 日期 2017-04-10
iOS 实现弱引用数组的几种方法

源于一道面试题的总结,由于要观察引用计数,所以以下代码都是基于 MRC 的 (其中 ARC 的代码也在注释里面)。

利用 block

注意 ARC 和 MRC 下的区别

// 方法 1 利用 block
typedef id(^WeakRefBlock)(void);
WeakRefBlock weakRef (id obj) {
// under MRC
__unsafe_unretained id weakObj = obj;
return [^{
return weakObj;
} copy];
// under ARC
// __weak id weakObj = obj;
// return ^{
// return weakObj;
// };
}
id getWeakObj(WeakRefBlock block){
if (block && [block isKindOfClass:NSClassFromString(@"NSBlock")]) {
return block();
}
return nil;
}

利用 CFArrayCreateMutable 或者 NSValue

@interface NSMutableArray (WeakRef)
// 方法 2 利用 CFArrayCreateMutable
// 初始化即是 weak array
+ (instancetype) unreatainedArray;
// 方法 3 利用 NSValue
// 添加 unretained 数据
- (void) unretainedAddObj:(NSObject *)obj;
// 获取 unretained 数据
- (NSObject *) unretainedObjectAtIndex:(NSUInteger)index;
@end
@implementation NSMutableArray (WeakRef)
+ (instancetype) unreatainedArray {
CFArrayCallBacks callbacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
return (id)CFBridgingRelease(CFArrayCreateMutable(0, 0, &callbacks));
}
- (void)unretainedAddObj:(NSObject *)obj {
NSValue *value = [NSValue valueWithNonretainedObject:obj];
[self addObject:value];
}
- (NSObject *)unretainedObjectAtIndex:(NSUInteger)index {
NSValue *value = [self objectAtIndex:index];
return [value nonretainedObjectValue];
}
@end

最后

使用弱引用数组记得要对取值进行检查,防止因为引用对象被释放的情况出现的 crash !

完整的代码请看 gist (ง •̀_•́)ง