NSUserDefaults详解

关于NSUserDefaults的一些原理

  1. 什么是NSUserDefaults

    对于应用来说,每个用户都有自己的独特偏好设置,而好的应用会让用户根据喜好选择合适的使用方式,把这些偏好记录在应用包的plist文件中,通过NSUserDefaults类来访问,这是NSUserDefaults的常用姿势。

  2. NSUserDefaults的存储位置

    \Library\Preferences\.plist
    

    由此可见本质上NSUserDefaults还是以plist形式存储的,并且存储在APP的沙盒中,若是删除了APP,相应设置也将不复存在

  3. 具体来说,NSUserDefaults是iOS系统提供的一个单例类(iOS提供了若干个单例类),通过类方法standardUserDefaults可以获取NSUserDefaults单例

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
  4. 既然本质是存储在plist中,那么能存储的数据也应该为plist支持的对象:

    NSData
    NSString
    NSNumber
    NSDate
    NSArray
    NSDictionary

    若是其余plist不支持的存储类型,可以将其转变为上述支持的类型再进行存储

  5. 从NSUserDefaults取到值是不可变的,即使之前存入的是可变的对象

    举个栗子,可变字符串,然后以stringForKey:方法取到字符串是不可变的,你做的修改并不会影响到NSUserDefaults里面存储的值,除非,利用 setObject:forKey:再次将改变后的对象重新赋值给那个key

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    UIImage *image =[UIImage imageNamed:@"XXXXX"];
    NSData *imageData = UIImageJPEGRepresentation(image, 100);//把image归档为NSData
    [defaults setObject:imageData forKey:@"image"];
    

简便方法存取不同类型数据

NSUserDefaults提供了若干简便方法可以存储某些常用类型的值,简化了设置,例如:

- setBool:forKey:
- setFloat:forKey:
- setInteger:forKey:
- setDouble:forKey:
- setURL:forKey:

NSUserDefaults域

user defaults数据库中其实是由多个层级的域组成的,当你读取一个键值的数据时,NSUserDefaults从上到下透过域的层级寻找正确的值,不同的域有不同的功能,有些域是可持久的,有些域则不行。

  • 应用域(application domain)是最重要的域,它存储着你APP通过NSUserDefaults set…forKey添加的设置。
  • 注册域(registration domain)仅有较低的优先权,只有在应用域没有找到值时才从注册域去寻找。
  • 全局域(global domain)则存储着系统的设置
  • 语言域(language-specific domains)则包括地区、日期等
  • 参数域( argument domain)有最高优先权

考虑这么一种情况:

BOOL showTutorialOnLaunch = [[NSUserDefaults standardUserDefaults] boolForKey:@"ShowTutorial"];

这种情况下,当key值@“ShowTutorial”已设置后会运行正确。但如果默认数据库没有这个key的默认值时,将会返回NO,这或许就不一定是你需要的值了,因为无法区分NOno value,前一段所提到的简便方法大多有这种问题。
解决方式:使用registerDefaults:方法
首先创建一个包含用户偏好设置信息的DefaultPreferences.plist文件,添加到target中。在运行时,app就可以加载这个文件并且把内容传到registerDefaults :

//APPDelegate.m --- application:didFinishLaunchingWithOptions
NSURL *defaultPrefsFile = [[NSBundle mainBundle]
URLForResource:@"DefaultPreferences" withExtension:@"plist"];
NSDictionary *defaultPrefs = [NSDictionary dictionaryWithContentsOfURL:defaultPrefsFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultPrefs];

PS. 需要在每次启动app并且没有在user defaules中读取数据的时候调用以上方法,因为registerDefaults:不能把这些默认数据存储到硬盘上,所以application:didFinishLaunchingWithOptions是最合适的地方。

默认情况下,应用域是空的,没键也没有值。当应用第一次设置某项用户偏好设置的值时,相应的值会通过指定的键加入应用域。当通过NSUserDefaults获取某项用户偏好设置的值时,NSUserDefaults会先在应用域中查找,如果找到了值,NSUserDefaults就会返回这个值。如果没有找到,NSUserDefaults就会在注册域中查找并返回默认值。

本文参考文章:

Class:NSUserDefaults
iOS/NSUserDefaults详解

你可能感兴趣的:(NSUserDefaults详解)