简介
项目开发中经常会申明变量保存相关相关值,但是对于功能太多的类中申明过多的变量看着就非常的繁琐,尤其是使用动态语言如javaScript 写过功能的都知道,动态语言可以动态的在一个对象上添加新的属性和值,这将是非常有诱惑力的功能,而且objective-c 的动态特性是非常强大的
oc 关联值
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
/**
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association.
* @param key The key for the association.
*
* @return The value associated with the key \e key for \e object.
*
* @see objc_setAssociatedObject
*/
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
以上两个oc 函数可以实现给给定对象设置关联值。但是查看相关api可知其中的key 是const void * 修饰的,也就是说给定的key 只能是同一个地址处的内容,对于多次添加需要定义多个key,这也是相当繁琐。故我们可以设置一个NSMutableDictionary 为对象的关联值,把需要动态设置的值保存到字典中即可。
新建NSObject 分类 NSObject+Ext.h
文件
//类似动态语言可以动态添加 键值对
@interface NSObject (Value)
//set value with nil will remove
-(void)zl_bindValue:(id)value forKey:(NSString *)key;
-(id)zl_value:(NSString *)key;
-(NSArray<NSString *> *)zl_keys;
//清空所有数据
-(void)zl_clearAll;
@end
NSObject+Ext.m
#import "NSObject+Ext.h"
#import <objc/runtime.h>
@implementation NSObject (Value)
static const char *cache_key = "$map_$cache_$object_$map_$key";
-(NSMutableDictionary *)zl_value_map:(BOOL)create{
NSMutableDictionary *map = objc_getAssociatedObject(self, cache_key);
if(map == nil && create){
map = [NSMutableDictionary dictionaryWithCapacity:16];
objc_setAssociatedObject(self, cache_key, map, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return map;
}
-(void)zl_bindValue:(id)value forKey:(NSString *)key{
[self zl_value_map:YES][key] = value;
}
-(id)zl_value:(NSString *)key{
return [self zl_value_map:NO][key];
}
-(NSArray<NSString *> *)zl_keys{
return [self zl_value_map:NO].allKeys;
}
-(void)zl_clearAll{
[[self zl_value_map:NO] removeAllObjects];
}
@end
测试
由上图可知动态添加属性成功!