实现字典有序化的方法
- 分类添加数组变量存储
key
值; - 按照
NSDictionary
的key
来进行排序; - 将字典中的
value
再放到一个字典里面key
分别有使用有序的字符串; - 先将字典转模型,再放到数组里面;
这里只说一下使用“分类添加数组变量存储 key 值“的方式实现字典的有序化
在Objective-C
中可以通过Category
给一个现有的类添加属性,但是不能添加实例变量。但是我们可以通过 Associated Objects 来解决这个问题,给NSMutableDictionary
添加一个NSMutableArray
的变量,来保存添加的key-value(键值对)
的 key
值。之后再通过Method Swizzling
来进行key
值的保存过程。
Associated Objects 相关的函数
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
OBJC_EXPORT void objc_removeAssociatedObjects(id object)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
*objc_setAssociatedObject
用于给对象添加关联对象,传入nil
则可以移除已关联的对象;
*objc_getAssociatedObject
用于获取关联对象;
*objc_removeAssociatedObjects
用于移除一个对象的所有的关联对象
具体的信息请移步博文 Objective-C Associated Objects 的实现原理
上代码
static const void *OrderedDictionaryKeys = (void *)@"OrderedDictionaryKeys";
-(NSMutableArray *)keys {
return objc_getAssociatedObject(self, OrderedDictionaryKeys);
}
- (void)setKeys:(NSMutableArray *)keys {
objc_setAssociatedObject(self, OrderedDictionaryKeys, keys, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
Method Swizzling
Method Swizzling
本质上就是对IMP
和SEL
进行交换。
具体了解请移步博文 iOS黑魔法-Method Swizzling
上代码
@implementation NSObject (Swizzling)
- (void)swizzlingMethod:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
Class class = [self class];
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
@end
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@autoreleasepool {
[objc_getClass("__NSDictionaryM") swizzlingMethod:@selector(setObject:forKey:) swizzledSelector:@selector(swizzled_setObject:forKey:)];
}
});
}
- (void)swizzled_setObject:(nonnull id)anObject forKey:(nonnull id<NSCopying>)aKey{
[self.keys addObject:aKey];
[self swizzled_setObject:anObject forKey:aKey];
}
#######OrderedMutableDictionary主要实现的方法
@interface NSMutableDictionary (Ordered)
NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, readonly, nullable) NSMutableArray *keys;
//获取给定index的对象
- (id)objectAtIndex:(NSUInteger)index;
//插入键值对至给定index
- (void)insertObject:(id)anObject forKey:(id<NSCopying>)aKey atIndex:(NSUInteger)index;
//插入键值对至给定index
- (void)removeLastObject;
//移除最后一个键值对
- (void)removeObjectAtIndex:(NSUInteger)index;
//移除给定index的键值对
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
//插入键值对至给定indexes
- (void)insertObjects:(NSArray<id> *)objects keys:(NSArray<id <NSCopying>> *)keys atIndexes:(NSIndexSet *)indexes;
//移除给定indexes的键值对
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes;
//替换给定indexes的值
- (void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray<id> *)objects;
NS_ASSUME_NONNULL_END
@end
本文最后附上demo地址:OrderedMutableDictionary