概述
数据存储是开发中必不可少的一个功能,我们可以通过Sqlite数据库手动创建数据库,定义数据表;可以使用IOS的数据框架CoreData,更方便的操作数据库;也可以直接读写文件系统;这里将介绍另外一种常用的方法:使用NSUserDefaults类,以字典形式保存数据,IOS会自动把字典中的键值对转换成对应的XML文件(也就是plist文件),这个文件会被保存到APP的沙盒目录中(路径为Library/Preferences/plist文件名)。
NSUserDefaults为我们封装了读写plist文件的常用操作,我们可以使用它来保存一些简单的数据,比如系统配置,用户设置的参数之类的。
了解plist文件
在学习使用NSUserDefaults类的用法前,我们需要先了解plist文件是一个什么文件,它是什么格式,可以保存哪些格式的数据。这样才能明白NSUserDefaults是干嘛用的!
当我们新建一个项目后,会发现有一个Info.plist文件,里面有很多参数配置:
不要被这些复杂的参数所迷惑,这只是Xcode的为我们自动生成的一个plist文件,用来保存当前项目的一些配置,Xcode为它集成了很多可用的Key和Value,这些都是预置的。
我们所要了解一个文件的本质,只需使用文本编辑器打开plist文件(也可以使用Xcode自带的功能:右键plist文件,Open As,Source Code)。我用的是CotEditor:
plist就是一个XML文件!key对应的就是键,string对应的就是值。
我们可以想像,NSUserDefaults为我们保存的就是这么一个xml文件,它的后缀名不叫xml而是plist,它会把我们代码中的Dictionary类型中的键值对转换成XML中对应的一个个节点。
plist中可以存储哪些数据类型
我们知道了plist是什么了之后,就该了解它的能力,也就是它能放哪些东西。
我们通过Xcode的plist文件编辑器,可以发现每一个键值对中间都有一个Type,不难理解这就是value的type,那有哪些type呢,右键即可:
集合类型(Array、Dictionary)
基本数据类型:(Boolean、Date、Number、String)
对象数据类型:(Data)
不难理解,也就这些数据可以被转换保存到一个纯文本文件(区别于二进制文件)中,其中Data类型稍微复杂点,在代码中我们会把某一个代码转换换NSData类型,然后IOS再把NSData转换为一长串乱码保存。
集合和基本数据类型对应的数据类型相信各位都清楚。
使用NSUserDefaults保存读取数据
接下来,看下如何使用NSUserDefaults这个类。在dash中,输如NSUserDefaults,根据几个分节点,我们可以知道,读数据用xxForKey,写数据用Setxx,删数据用removeObjectForKey。
可以看到,读方法中有很多不同类型的方法,我们可以根据不同的数据类型来选择使用的读取方法,写方法也类似。
我们选中其中一个方法,可以看到它是一个普通的func,不是类方法,也就是说,我们需要使用NSUserDefault类的实例来调用。
有2中方法,第一种就是使用构造函数init(),第二种是调用standardUserDefaults属性获得一个默认的对象。
两者区别是,创建plist文件时所使用的Domain,使用init构造函数时,不考虑Domain环境,直接在当前App的沙盒目录下创建plist文件,使用项目的bundle identifier字符串作为plist文件的文件名。
使用standardUserDefaults时考虑Domain环境,默认也是也是使用bundle identifier作为plist文件的文件名。另外支持NSGlobalDomain和NSRegistrationDomain,这一块就不详细展开了(因为我也还没理解…)
println(NSHomeDictionary()) let userDef = NSUserDefaults() userDef.setInteger(1234, forKey: "count") userDef.setObject("nice", forKey: "result") userDef.setBool(true, forKey: "isShow") userDef.setDouble(12.5, forKey: "point")
这段代码运行后,ios便会为我们创建一个plist文件,根据NSHomeDictionary方法返回的路径,打开目录,进入Library/Preferences目录:
使用Xcode打开:
写入数据,就这么简单,读取数据也同理:
println(userDef.integerForKey("count")) println(userDef.objectForKey("result")) println(userDef.boolForKey("isShow")) println(userDef.doubleForKey("point"))
Data类型的保存
NSUserDefaults支持保存对象类型,前提是需要把对象转为NSData。
对象转换为NSData,我们把这个过程成为序列化或者叫编码~可以看这一篇详细介绍:《IOS中对象序列化与反序列化》
var person = Person() person.name = "lijialong" person.age = 26 let defa = NSUserDefaults() //把Person对象保存到plist文件中,键值名为Person defa.setObject(person, forKey: "Person") defa.synchronize()
registerDefaults方法的使用
NSUserDefaults除了保存和读取功能外,还为我们提供了一个很便捷的方法:registerDefaults。
func registerDefaults(registrationDictionary: [NSObject : AnyObject])
它的参数是一个字典类型。它的作用是为定义一组默认的数据,仅仅是定义一组默认的数据…这些默认的数据是不会被保存到plist文件中的,我们需要手动变更这些数据然后保存。
举一个栗子,我们可以使用这个方法来确认App是否是第一次启动:
let defa = NSUserDefaults() //注册一个默认值 defa.registerDefaults(["firstRun":true]) //从plist文件中读取内容,因为第一次启动还没有生成plist文件,所以读取上面注册的默认值 let isFirstRun = defa.boolForKey("firstRun") //是第一次启动 if(isFirstRun){ println("这是第一次启动") //手动把firstRun改为false,保存到plist中 defa.setBool(false, forKey: "firstRun") } else{ println("不是第一次启动") }
registerDefaults方法中的字典数据是不会被保存到plist文件中的,当我们读取某个键值时,如果plist中没有找到,那么会从registerDefaults方法的字典参数中寻找对应的键值,拿到默认值。当我们做了相应处理后,再手动把这个键值内容保存到plist中,下次读取是就会直接读plist文件中的键值了,而不会读取registerDefaults参数中的字典内容了。