前言
將一個(gè)對(duì)象添加到一個(gè)array或dictornary里一件很常見的事淆衷,一般不會(huì)遇到問(wèn)題旺遮。但是如果這個(gè)容器會(huì)一直存在的靜態(tài)全局對(duì)象時(shí)培己,就會(huì)影響object的釋放,造成內(nèi)存泄露贿堰。起初已為定義一個(gè)__weak object,然后把它作為參數(shù)就可以,太異想天開了鹿驼,這種仍然會(huì)strong引用鸣剪。
主要的解決方法有三種:
1.NSValue
可以使用的 valueWithNonretainedObject:view方法來(lái)弱引用一個(gè)對(duì)象
NSValue *key = [NSValue valueWithNonretainedObject:view];
[dic setObject:outlineView forKey:key];
2.NSMapTable, NSPointerArray零蓉,NSHashTable
NSMapTable有兩個(gè)初始化的方法
- (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 是內(nèi)存管理策略的枚舉值卿嘲,主要有NSPointerFunctionsWeakMemory,NSPointerFunctionsStrongMemory兩個(gè)值淀弹,代表弱引用和強(qiáng)引用丹壕。而NSPointerFunctionsWeakMemory就是我們想要的。不僅如此薇溃,NSMapTable的key和value都可以分別設(shè)置弱引用或強(qiáng)引用菌赖,非常強(qiáng)大。
如果弱引用的對(duì)象被釋放了會(huì)怎么樣痊焊?
如果key對(duì)象被釋放, key=nil盏袄,那么key和value都會(huì)被移除,至少遍歷的時(shí)候不會(huì)遍歷掉薄啥。
如果value對(duì)象被釋放,那么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非常相似,它是一個(gè)可變的绰寞、可插入null的數(shù)組到逊,可以設(shè)置弱引用
NSHashTable
類似于NSMutableSet铣口,支持弱引用,可變的觉壶、可插入null的set
NSFastEnumeration協(xié)議
我們經(jīng)常發(fā)現(xiàn)集合類都實(shí)現(xiàn)了NSFastEnumeration這個(gè)協(xié)議脑题,像NSArray,NSDictionary, NSMapTable, NSHashTable等等。
協(xié)議的定義:
@protocol NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer count:(NSUInteger)len;
@end
實(shí)現(xiàn)NSFastEnumeration這個(gè)協(xié)議铜靶,就會(huì)支持for/in語(yǔ)法糖叔遂,但并不代表會(huì)有enumerateObjectsUsingBlock
方法,這個(gè)方法是NSArray自己定義實(shí)現(xiàn)的争剿。還有當(dāng)自定義類實(shí)現(xiàn)countByEnumeratingWithState
方法時(shí)已艰,要根據(jù)不同的數(shù)組存儲(chǔ)類型選擇適合自己的一套算法實(shí)現(xiàn),這里其實(shí)并沒有固定算法蚕苇。