iOS-浅谈NSUserDefaults保存数据的缺点以及改进方
在iOS开发当中,我们难免会遇到保存数据的情况,即数据的本地永久存储。其中,NSUserDefaults是最常使用的轻量级的数据存储方式。今天小编就来简单谈一下NSUserDefaults。
相信是个iOS程序猿都使用过NSUserDefaults来保存数据,因为实在是太过简单,只需要使用使用两行代码就能保存了,如下:
图1:NSUserDefaults的使用使用NSUserDefaults来存取数据代码非常简单,但是很多人却并不知道苹果内部是如何保存这个key-value的。这里就简单来说一下:iOS系统是以一个.plist文件来统一管理这些使用NSUserDefaults保存的key-value的。大家可以参考你所在项目中的info.plist.
当然,我们可以验证一下:在代码当中执行NSHomeDirectory()并打印,复制,然后在Finder->前往->前往文件夹中粘贴前往,或者才终端中执行"cd 刚才复制的路径"->"open ."来前往所在沙河路径。其中NSUserDefaults就保存在/Library/Preference中。
下面就看一下我一个demo中的plist文件:
图2:NSUserDefaults保存数据的plist文件从图2当中的.plist文件可以看到其与工程当中的info.plist文件是一样的,同时还要说一些题外话,那就是NSUserDefaults还有一些别的知识点,比如图2中的suitename等,详情请参考文档,这里不详细解释。
说使用NSUserDefaults大家都会用,但是像图1那样写代码实在是太恶心了,因为这个样子写数据根本没有统一规划,而且取值的时候十分不方便。
比如做视频播放器时常用到的下面这个:
图3:允许流量播放根据图3的显示可以知道需求:当UISwitch关闭时不允许播放视频。这是一个很常见的产品需求,但是如果按照图1的方式来写,那岂不是要在很多地方写[userDefaults objectForKey:@"key"]?所以,我们应摒弃像图1的那种方式使用NSUserDefaults。
当然,也有很多人想到了别的方法来解决图1那样写代码所带来的困扰,比如创建一个类文件来声明所有的key值等!但是那样子也难免有些麻烦,代码写起来也有些繁琐。
现在小编就来说说我的解决办法:NSUserDefaults+单例+runtime。我写的这个东西已经上传到Github,项目名称为NSUserDefaultsModel,并可以支持Cocoapods。
废话不多说,我这里就来解释NSUserDefaultsModel的思想以及用法:
1.NSUserDefaultsModel是一个单例,可以实现App内部各个类之间的数据共享。
2.继承自NSUserDefaultsModel创建一个子类,比如LCUserDefaultsModel,并在.h文件中声明一些属性,这些属性就是作为plist文件的key值存在的,如下:
图4:属性3.在.m文件当中对每一个属性进行@dynamic操作,意为setter与getter方法由类自己实现,如下:
图5:@dynamic操作4.如果想对属性设置默认值,那么需要重写setupDefaultValues方法,如下:
图6:默认值操作其中,图6字典的规则是@{@"属性的字符串": @"默认值"}
5.以“name”来说,如果想要进行取值的话只需要调用[LCUserDefaultsModel userDefaultsModel].name就行,对"name"进行更改并保存到plist文件的话只需要调用[LCUserDefaultsModel userDefaultsModel].name = @"newName"就可以了。
其实说到NSUserDefaultsModel这个小型的替代系统NSUserDefaults的第三方库实现原理是:基于Objective-C的Runtime机制来重写NSUserDefaultsModel子类的属性方法,即Setter方法与Getter方法。NSUserDefaultsModel用到的Runtime的方法有:
1.objc_property_t,property_getName和property_getAttributes这三个方法是用来获取属性Property的相关信息。
2.class_addMethod是为对象增加方法,也就是属性的Setter与Getter方法。
代码小编已上传到Github,项目名称为NSUserDefaultsModel,并可以支持Cocoapods,欢迎大家支持。捎带说一句:别吝啬你手里的星星。
(注:以后小编还会根据同样的思想来实现FMDB数据库的存取)