NSMutableDictionary实现原理分析

不积跬步无以至千里。 ——送给第一篇博客

问题

NSMutableDictionary是怎么实现的?

解决方案

学习实现原理最好的办法就是查看源代码,这部分代码也很容易找到

/****************   Mutable Dictionary  ****************/

@interface NSMutableDictionary<KeyType, ObjectType> : NSDictionary<KeyType, ObjectType>

- (void)removeObjectForKey:(KeyType)aKey;
- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCapacity:(NSUInteger)numItems NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

@end

@interface NSMutableDictionary<KeyType, ObjectType> (NSExtendedMutableDictionary)

- (void)addEntriesFromDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary;
- (void)removeAllObjects;
- (void)removeObjectsForKeys:(NSArray<KeyType> *)keyArray;
- (void)setDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary;
- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key NS_AVAILABLE(10_8, 6_0);

@end

从源代码中我们可以看到NSMutableDictionary是继承自NSDictionary的,但是添加了增加删除等方法。将NSDictionary变成可变的字典类型。我们再打开NSDictionary的实现代码看一下。

@interface NSDictionary<KeyType, ObjectType> (NSExtendedDictionary)

@property (readonly, copy) NSArray<KeyType> *allKeys;//key数组
- (NSArray<KeyType> *)allKeysForObject:(ObjectType)anObject;
@property (readonly, copy) NSArray<ObjectType> *allValues;//value数组
@property (readonly, copy) NSString *description;

我们可以看到NSDictionary中包含了两个NSArray,及一个对应Key的NSArray和一个对应Value的NSArray。
从以上两端代码中我们可以看到NSDictionary以及NSArray的属性均为(readonly,copy)类型的,顾名思义其值是只读的,不可改变。这也符合了介绍,但是NSMutableDictionary以及NSMutableArray均继承于属性不可变的父类,那他是怎么实现可变的呢?由于SDK只开放了.h文件(其实就是只告诉了我们API),没有开放.m文件,我们无法获得其实现细节。我的猜测是把内容拷贝出来重新赋值给新的对象,在替换原地址,但是感觉好蠢。以后有能力可以细究一下。

意外发现

看源代码的时候发现NSArray中集成二分查找,但二分查找一般针对排序数组会有比较快的效率。百度了一下,发现一篇文章 ,这篇文章对iOS的各种集合类做了一定的分析。其中也提到了一开始对apple这种将很多集合分为可变和不可变的感觉很怪异,不过这样做可以使得其线程安全,这样其付出的代价也是值得的,有兴趣可以拜读一下。

typedef NS_OPTIONS(NSUInteger, NSBinarySearchingOptions) {
    NSBinarySearchingFirstEqual = (1UL << 8),
    NSBinarySearchingLastEqual = (1UL << 9),
    NSBinarySearchingInsertionIndex = (1UL << 10),
};

- (NSUInteger)indexOfObject:(ObjectType)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts usingComparator:(NSComparator)cmp NS_AVAILABLE(10_6, 4_0); // binary search
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容