NSPointerArray屁擅、NSMapTable、NSHashTable是iOS 6.0之后新增的集合類型产弹,對應于原來的NSArray派歌、NSSet、NSDictionary。
NSPointerArray
NSPointerArray和NSArray/NSMutableArray一樣胶果,用于有序的插入或移除常挚。不同的是:
- 可以存儲 nil,并且 nil 還參與 count 的計算稽物。
- count 值可以直接設置奄毡,如果直接設置count,那么會使用 nil 占位贝或。
- 可以使用 weak 來修飾元素吼过,可以添加所有的指針類型。
- 可以通過 for...in 來進行遍歷咪奖。
也有一些缺點:
- 操作均基于 index盗忱,無法通過 object 來進行操作;
- 無法直接插入 array羊赵,或用 array 初始化趟佃;
- 查找功能沒有 NSArray 強大;
- 沒有逆序昧捷、排序等 API 提供
初始化
NSPointerArray 有兩個初始化方法:
- (instancetype)initWithOptions:(NSPointerFunctionsOptions)options;
- (instancetype)initWithPointerFunctions:(NSPointerFunctions *)functions;
+ (NSPointerArray *)pointerArrayWithOptions:(NSPointerFunctionsOptions)options;
+ (NSPointerArray *)pointerArrayWithPointerFunctions:(NSPointerFunctions *)functions;
NSPointerFunctionsOptions主要分為三大類:
內存管理
- NSPointerFunctionsStrongMemory:缺省值闲昭,在 CG 和 MRC 下強引用成員
- NSPointerFunctionsZeroingWeakMemory:已廢棄,在 GC 下靡挥,弱引用指針序矩,防止懸掛指針
- NSPointerFunctionsMallocMemory 與 NSPointerFunctionsMachVirtualMemory:3 用于 Mach 的虛擬內存管理
- NSPointerFunctionsWeakMemory:在 CG 或者 ARC 下,弱引用成員
特性跋破,用于標明對象判等方式
- NSPointerFunctionsObjectPersonality:hash簸淀、isEqual、對象描述
- NSPointerFunctionsOpaquePersonality:pointer 的 hash 毒返、直接判等
- NSPointerFunctionsObjectPointerPersonality:pointer 的 hash租幕、直接判等、對象描述
- NSPointerFunctionsCStringPersonality:string 的 hash拧簸、strcmp 函數(shù)劲绪、UTF-8 編碼方式的描述
- NSPointerFunctionsStructPersonality:內存 hash、memcmp 函數(shù)
- NSPointerFunctionsIntegerPersonality:值的 hash
內存標識
- NSPointerFunctionsCopyIn:根據(jù)第二類的選擇狡恬,來具體處理珠叔。
可以使用多個組合進行初始化:
NSPointerFunctionsOptions opt = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;
NSPointerArray *point = [[NSPointerArray alloc]initWithOptions:opt];
NSPointerFunctions
使用NSPointerFunctions可以自定義NSPointerArray對元素的處理方式:如何內存管理、如何hash弟劲、如何判斷相等(isEqual)祷安。
NSPointerFunctions初始化時可設置NSPointerFunctionsOptions
:
- (instancetype)initWithOptions:(NSPointerFunctionsOptions)options;
+ (NSPointerFunctions *)pointerFunctionsWithOptions:(NSPointerFunctionsOptions)options;
如果需要自定義實現(xiàn)函數(shù),可以使用下面的對應屬性:
// 自定義指針函數(shù)
// hash函數(shù)
@property (nullable) NSUInteger (*hashFunction)(const void *item, NSUInteger (* _Nullable size)(const void *item));
// isEqual函數(shù)
@property (nullable) BOOL (*isEqualFunction)(const void *item1, const void*item2, NSUInteger (* _Nullable size)(const void *item));
// size函數(shù)
@property (nullable) NSUInteger (*sizeFunction)(const void *item);
// 描述函數(shù)
@property (nullable) NSString * _Nullable (*descriptionFunction)(const void *item);
// 自定義內存配置
// 移除元素時的處理函數(shù)
@property (nullable) void (*relinquishFunction)(const void *item, NSUInteger (* _Nullable size)(const void *item));
// 添加元素時的處理函數(shù)
@property (nullable) void * _Nonnull (*acquireFunction)(const void *src, NSUInteger (* _Nullable size)(const void *item), BOOL shouldCopy);
可以自行實現(xiàn)函數(shù),然后將函數(shù)指針賦給對應屬性即可兔乞,比如汇鞭,isEqual:
static BOOL IsEqual(const void *item1, const void *item2, NSUInteger (*size)(const void *item)) {
return *(const int *)item1 == *(const int *)item2;
}
NSPointerFunctions *functions = [[NSPointerFunctions alloc] init];
[functions setIsEqualFunction:IsEqual];
操作數(shù)組
添加元素:
- (void)addPointer:(nullable void *)pointer;
移除元素:
- (void)removePointerAtIndex:(NSUInteger)index;
插入元素:
- (void)insertPointer:(nullable void *)item atIndex:(NSUInteger)index;
替換元素:
- (void)replacePointerAtIndex:(NSUInteger)index withPointer:(nullable void *)item;
如果想實現(xiàn)類似Array的根據(jù)下標賦值,可以為它添加一個分類:
@interface NSPointerArray(Set)
/// 設置目標位置的值
- (void)setObject:(id)anObject
atIndex:(NSUInteger)idx;
@end
@implementation NSPointerArray(Set)
- (void)setObject:(id)anObject
atIndex:(NSUInteger)idx{
if (self.count > idx) {
self.count = idx + 2;
}
[self insertPointer:(__bridge void * _Nullable)(anObject) atIndex:idx];
}
@end
NSMapTable
與 NSMapTable 對應的凉唐,是 NSMutableDictionary。除了 集合的共有特點以外霍骄,比起傳統(tǒng)字典台囱,它還有一些優(yōu)勢:
- key 可以不用遵循 NSCopying 協(xié)議;
- key 和 value 的內存管理方式可以分開读整,如:key 是強引用簿训,value 是弱引用;
相比起 NSPointerArray米间,NSMapTable 的初始化方法要多得多:
// 雖然有 capacity 參數(shù)强品,但實際沒用到
- (instancetype)initWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions capacity:(NSUInteger)initialCapacity;
- (instancetype)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)initialCapacity;
+ (NSMapTable<KeyType, ObjectType> *)mapTableWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions;
// 返回指定 key、value 內存管理類型的 map
+ (NSMapTable<KeyType, ObjectType> *)strongToStrongObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)weakToStrongObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)strongToWeakObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)weakToWeakObjectsMapTable NS_AVAILABLE(10_8, 6_0);
其實屈糊,這么多的初始化方法就對應著四種搭配:
- key 為 strong的榛,value 為 strong
- key 為 strong,value 為 weak
- key 為 weak逻锐,value 為 strong
- key 為 weak夫晌,value 為 weak
當用 weak 修飾 key 或 value 時,有一方被釋放昧诱,則該鍵值對移除晓淀。
NSHashTable
NSHashTable 對應 NSMutableSet,它的 API 更為簡單鳄哭,與 NSMapTable 同樣要糊,初始化方法的 capacity 并未生效纲熏。
- (instancetype)initWithOptions:(NSPointerFunctionsOptions)options capacity:(NSUInteger)initialCapacity;
- (instancetype)initWithPointerFunctions:(NSPointerFunctions *)functions capacity:(NSUInteger)initialCapacity;
值得注意的是妆丘,NSHashTable 有一個 allObjectes 的屬性,返回 NSArray局劲,即使 NSHashTable 是弱引用成員勺拣,allObjects 依然會對成員進行強引用。