美文网首页
NSHashMap / NSHashTable / NSPoi

NSHashMap / NSHashTable / NSPoi

作者: 哦小小树 | 来源:发表于2020-05-10 23:33 被阅读0次

0x01 场景分析

需要创建一个集合,但是又不想让集合引用内部变量,这样就可以在内部变量被销毁是,不会因为集合引用了这个变量而导致无法被销毁。
如果我们使用NSMutableSet来进行操作,就会因为NSMutableSet对内部的元素多一个强引用导致无法释放。那么有没有其他集合方案可以让我们自由控制内存引用关系呢。

iOS6.0是就已经提供了支持,目的是为了拓展集合对内部元素的引用关系。
NSHashTable 相当于NSMutableSet,但是可以对其内部的引用关系做额外设置,不像NSMutableSet只是用来做强引用。


0x02 NSHashTable

NSHashTable允许我们自定义集合对其内部元素的内存引用方案。更广泛意义的NSSet,区别于NSSet/NSMUtableSet, NSHashTable有以下特性

  • 可变
  • 可以持有weak类型的成员变量
  • 可以再添加成员变量的时候复制成员
  • 可以任意的存储指针,并且利用指针的唯一性来进行对比和重复检查。

可行的方案

// 对成员变量进行强引用
NSHashTableStrongMemory /   NSPointerFunctionsStrongMemory

// 在ARC下使用弱引用方式进行读写,在最后一次释放后,引用对象将会被置为NULL
NSHashTableWeakMemory   /   NSPointerFunctionsWeakMemory

// 在对象被加入到集合中前进行复制
NSHashTableCopyIn   /   NSPointerFunctionsCopyIn

// 用指针来等同替代实际的值,当打印这个指针时,相当于调用了description方法
NSHashTableObjectPointerPersonality / NSPointerFunctionsObjectPointerPersonality
// 存储时,对要存储的对象A进行弱引用,当A被释放时,会自动在table中移除
NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
// NSHashTable *table = [NSHashTable weakObjectsHashTable]; 功能一样

Aobj *a = [Aobj new];
[table.addObject:a];

// 强引用,与NSMUtableSet功能一样
NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory];
Aobj *a = [Aobj new];
[table.addObject:a];

0x03 NSMapTable

NSMapTable是更广泛意义的NSMutableDictionary,我们可以自定义内存管理方案。

NSDictionary/NSMutableDictionary会赋值keys并且通过强引用value来实现存储。

NSMapTableNSDictionary/NSMUtableDictionary相比具有以下特性:

  • 可变
  • 可以通过弱引用来持有keysvalues,所以当key或者valuedeallocated的时候,所存储的实体也会被移除。
  • 可以在添加value的时候对value进行复制
  • 可以任意的存储指针 ,并且利用指针的唯一性来进行对比和重复性检测。
    可行性方案:
// 对成员变量进行强引用
NSMapTableStrongMemory / NSPointerFunctionsStrongMemory

// 对成员变量进行弱引用
NSMapTableWeakMemory

// 在对象被加入到字典中前进行复制
NSMapTableCopyIn    / NSPointerFunctionsCopyIn.

// 用指针来等同替代实际的值
NSMapTableObjectPointerPersonality / NSPointerFunctionsObjectPointerPersonality
    NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableCopyIn                                              valueOptions:NSMapTableCopyIn];     // value使用copyIn,Person需要实现NSCopying协议
        {
            Person *p = [Person new];
            [mapTable setObject:p forKey:@"foo"];
        }
        NSLog(@"Keys: %@", [[mapTable keyEnumerator] allObjects]);
        NSLog(@"values:%@",[mapTable objectForKey:@"foo"]);
        

注意:NSMapTable不能继承subscripting
因为下标访问需要一个id作为key,对于NSMapTable来说,这不是强制的。


0x04 NSPointArray

一个稀疏数组,与NSMutableArray相似,但可以存储NULL值。如果存在NULL索引会发生改变。
在性能方面,NSPointerArray非常慢,所以当你打算在一个很大的数据集合上使用它时一定要三思。

可行性方案:

// 对成员变量进行强引用
NSPointerFunctionsStrongMemory

// 对成员变量进行弱引用
NSPointerFunctionsWeakMemory

// 在加入集合前执行copy
NSPointerFunctionsCopyIn

// 使用对象的hash和isEqual:(默认)。
NSPointerFunctionsObjectPersonality

// 对于isEqual:和hash使用直接的指针比较。
NSPointerFunctionsObjectPointerPersonality

NSPointerArray *ptrArray  = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsWeakMemory];
// NSPointerArray *ptrArray  = [NSPointerArray weakObjectsPointerArray];    效果一样
        for (int i = 0; i < 3; i ++)
        {
            Person *p = [Person new];
            [ptrArray addPointer:(__bridge void *)p];
        }
        void *a = (__bridge void *)@10;
        // void *a = 10;    会crash,原因就是在
        [ptrArray addPointer:a];
        NSLog(@"---%@",ptrArray.allObjects);

0x05 NSPointerFunctionsOptions

是一个option,主要分为三大类:

内存管理语义

// 缺省值,在 CG 和 MRC 下强引用成员
NSPointerFunctionsStrongMemory

// 在指针去除时不做任何动作
NSPointerFunctionsOpaqueMemory 

// 用于 Mach 的虚拟内存管理
NSPointerFunctionsMallocMemory 与 NSPointerFunctionsMachVirtualMemory

// 在 CG 或者 ARC 下,弱引用成员
NSPointerFunctionsWeakMemory

特性

对象处理选项即如何进行哈希算法,判定同等性,描述

// 使用NSObject的hash, isEqual, description,默认
NSPointerFunctionsObjectPersonality

//使用偏移后指针,进行hash和直接比较同等性
NSPointerFunctionsOpaquePersonality

// 和上一个相同,多了description方法
NSPointerFunctionsObjectPointerPersonality

// 使用C字符串的hash、strcmp 函数、UTF-8 编码方式的描述
NSPointerFunctionsCStringPersonality

// 使用内存的hash、memcmp
NSPointerFunctionsStructPersonality

// 使用偏移量作为hash和等同性判断
NSPointerFunctionsIntegerPersonality

内存标识

// 根据第二类的选择,来具体处理
// 如果是 NSPointerFunctionsObjectPersonality,则根据 NSCopying 来拷贝。
NSPointerFunctionsCopyIn

注意: 每种类别的选项只能选择一个

所以在使用时,可以多个组合。比如:需要强引用成员,使用对象方式对比,并且addcopy对象

NSPointerFunctionsOptions *options = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;

0x06 总结

正常情况下我们使用NSArray/NSMutableArrayNSSet/NSMutableSetNSDictionary/NSMutableDictionary就可以达到90%以上的需求。如果自定义程度更高,我们就可以去考虑使用NSHashTable,NSMapTable,NSPointerArray来解决问题。


参考:
https://blog.csdn.net/u012597860/article/details/51240430
https://www.cnblogs.com/zhaoguowen/p/4273237.html
https://www.cnblogs.com/lxlx1798/p/6651949.html

相关文章

网友评论

      本文标题:NSHashMap / NSHashTable / NSPoi

      本文链接:https://www.haomeiwen.com/subject/cacpwhtx.html