NSUserDefaults简易封装库GVUserDefaults

平常开发我们一般用NSUserDefaults来保存一些简单的数据,比如应用程序配置,NSUserDefaults提供了一系列类似于NSDictionary方法:

- (void)setObject:(nullable id)value forKey:(NSString *)defaultName 

- (nullable id)objectForKey:(NSString *)defaultName;

- (void)removeObjectForKey:(NSString *)defaultName;

我们需要保存、查询、删除配置项的话,都需要传递key以调用NSUserDefaults的方法,如果能把取配置项的操作封装成属性操作,那用起来就方便多了,GVUserDefaults就是类似这样的封装。

一、GVUserDefaults用法:

详细用法见github链接GitHub - gangverk/GVUserDefaults: NSUserDefaults access via properties.支持功能如下:

1、通过定义setupDefaults方法设置配置项默认值

2、通过定义- (NSString *)transformKey:(NSString *)key方法设置键值的保存名称,比如你属性定义的是name,但是保存时想定义为DDName。

3、通过定义suitName方法让NSUserDefaults通过initWithSuiteName初始化,以支持App共享配置

二、GVUserDefaults实现原理

1、实现原理很简单,通过运行时动态加入属性的set和get方法来实现GVUserDefaults属性的设置和获取。standardUserDefaults->init->generateAccessorMethods. 方法generateAccessorMethods通过遍历GVUserDefaults扩展定义的属性,根据属性的类型,为每个属性生成set和get方法,代码如下:

- (void)generateAccessorMethods {

unsigned int count = 0;

objc_property_t *properties = class_copyPropertyList([self class], &count);

self.mapping = [NSMutableDictionary dictionary];

for (int i = 0; i < count; ++i) {

objc_property_t property = properties[i];

const char *name = property_getName(property);

const char *attributes = property_getAttributes(property);

char *getter = strstr(attributes, ",G");

if (getter) {

getter = strdup(getter + 2);

getter = strsep(&getter, ",");

} else {

getter = strdup(name);

}

SEL getterSel = sel_registerName(getter);

free(getter);

char *setter = strstr(attributes, ",S");

if (setter) {

setter = strdup(setter + 2);

setter = strsep(&setter, ",");

} else {

asprintf(&setter, "set%c%s:", toupper(name[0]), name + 1);

}

SEL setterSel = sel_registerName(setter);

free(setter);

NSString *key = [self defaultsKeyForPropertyNamed:name];

[self.mapping setValue:key forKey:NSStringFromSelector(getterSel)];

[self.mapping setValue:key forKey:NSStringFromSelector(setterSel)];

IMP getterImp = NULL;

IMP setterImp = NULL;

char type = attributes[1];

switch (type) {case Short:

case Long:

case LongLong:

case UnsignedChar:

case UnsignedShort:

case UnsignedInt:

case UnsignedLong:

case UnsignedLongLong:

getterImp = (IMP)longLongGetter;

setterImp = (IMP)longLongSetter;

break;

case Bool:

case Char:

getterImp = (IMP)boolGetter;

setterImp = (IMP)boolSetter;

break;

case Int:

getterImp = (IMP)integerGetter;

setterImp = (IMP)integerSetter;

break;

case Float:

getterImp = (IMP)floatGetter;

setterImp = (IMP)floatSetter;

break;

case Double:

getterImp = (IMP)doubleGetter;

setterImp = (IMP)doubleSetter;

break;

case Object:

getterImp = (IMP)objectGetter;

setterImp = (IMP)objectSetter;

break;

default:

free(properties);

[NSException raise:NSInternalInconsistencyException format:@"Unsupported type of property \"%s\" in class %@", name, self];

break;

}

char types[5];

snprintf(types, 4, "%c@:", type);

class_addMethod([self class], getterSel, getterImp, types);

snprintf(types, 5, "v@:%c", type);

class_addMethod([self class], setterSel, setterImp, types);

}

free(properties);

}

2、也可以通过消息转发机制实现属性set方法和get方法,通过覆盖+ (BOOL)resolveInstanceMethod:(SEL)sel来实现

你可能感兴趣的:(NSUserDefaults简易封装库GVUserDefaults)