数组或字典如何弱引用对象

前言

将一个对象添加到一个array或dictornary里一件很常见的事,一般不会遇到问题。但是如果这个容器会一直存在的静态全局对象时,就会影响object的释放,造成内存泄露。起初已为定义一个__weak object,然后把它作为参数就可以,太异想天开了,这种仍然会strong引用。

主要的解决方法有三种:

1.NSValue
可以使用的 valueWithNonretainedObject:view方法来弱引用一个对象

        NSValue *key = [NSValue valueWithNonretainedObject:view];
        [dic setObject:outlineView forKey:key];

2.NSMapTable, NSPointerArray,NSHashTable

NSMapTable有两个初始化的方法

- (instancetype)initWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;

NSPointerFunctionsOptions 是内存管理策略的枚举值,主要有NSPointerFunctionsWeakMemory,NSPointerFunctionsStrongMemory两个值,代表弱引用和强引用。而NSPointerFunctionsWeakMemory就是我们想要的。不仅如此,NSMapTable的key和value都可以分别设置弱引用或强引用,非常强大。
如果弱引用的对象被释放了会怎么样?
如果key对象被释放, key=nil,那么key和value都会被移除,至少遍历的时候不会遍历掉。
如果value对象被释放,那么key存在,value=nil

我们将Key和value都弱引用,示例如下:

_table = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsWeakMemory valueOptions:NSPointerFunctionsWeakMemory capacity:4];
    [_table setObject:[UIView new] forKey:@"weakKey"];
    [_table setObject:self.view forKey:@"strongKey"];

NSPointerArray
它的初始化跟NSMapTable非常相似,它是一个可变的、可插入null的数组,可以设置弱引用
NSHashTable
类似于NSMutableSet,支持弱引用,可变的、可插入null的set

NSFastEnumeration协议

我们经常发现集合类都实现了NSFastEnumeration这个协议,像NSArray,NSDictionary, NSMapTable, NSHashTable等等。
协议的定义:

@protocol NSFastEnumeration

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer count:(NSUInteger)len;

@end

实现NSFastEnumeration这个协议,就会支持for/in语法糖,但并不代表会有enumerateObjectsUsingBlock方法,这个方法是NSArray自己定义实现的。还有当自定义类实现countByEnumeratingWithState方法时,要根据不同的数组存储类型选择适合自己的一套算法实现,这里其实并没有固定算法。

你可能感兴趣的:(数组或字典如何弱引用对象)