数据持久化
1.plist文件
即属性列表文件,全名是property list,这种文件的扩展名为.plist,因此,通常被叫做plist文件。它是一种用来存储串行化后的对象的文件,用于存储程序中经常用到且数据量小而不经常改动的数据。
可以存储的类型:nsnumber,nsstring,nsdate,nsdata ,nsarray,nsdictionary,bool.
不支持自定义对象的存储。
plist的创建方式有两种:command + n 创建和纯代码创建,不同的创建方式使用方法也自然不同。
command + n 创建:
// read bundle's plist
if let plistpath = bundle.main.path(forresource: "test", oftype: "plist") {
var datadict = nsdictionary(contentsoffile: plistpath) as! dictionary<string, any>
// var dataarray = nsarray(contentsoffile: plistpath) as! nsarray
// modify
datadict["int"] = 1
datadict["string"] = "hi"
}
纯代码创建:
// create
let documentspath = nssearchpathfordirectoriesindomains(.documentdirectory, .userdomainmask, true)[0] as nsstring
let plistpath = documentspath.appendingpathcomponent("test.plist")
print(plistpath)
// write
var dict = [string: any]()
dict["int"] = 1
dict["bool"] = true
(dict as nsdictionary).write(tofile: plistpath, atomically: true)
// read
if let datadict = nsdictionary(contentsoffile: plistpath) {
print(datadict)
}
需要注意的问题:如果需要存储自定义类型的数据需要先进行序列化。
2.nsuserdefaults
用于存储用户的偏好设置、用户信息(如用户名、是否自动登录、字体大小等)。
数据自动保存在沙盒的libarary/preferences 目录下。
nsuserdefaults将输入的数据储存在.plist格式的文件下,这种存储方式就决定了它的安全性几乎为0,所以不建议存储一些敏感信息如:用户密码、token、加密私钥等。
它能存储的数据类型为:nsnumber(nsinteger、float、double、bool),nsstring,nsdate,nsarray,nsdictionary,nsdata。
不支持自定义对象的存储。
需要注意的问题: 1.nsuserdefaults存储的数据都是不可变的,想将可变数据存入需要先转为不可变才可以存储。
2.nsuserdefaults是定时把缓存中的数据写入磁盘的,而不是即时写入,为了防止在写完nsuserdefaults后程序退出导致的数据丢失,可以在写入数据后使用synchronize强制立即将数据写入磁盘。
/// code block:
func testuserdefaults() -> void {
let standard = userdefaults.standard
standard.set(1, forkey: "int")
standard.set(true, forkey: "bool")
standard.set(1.0, forkey: "float")
standard.synchronize()// 立即存储
if let v_int = standard.object(forkey: "int") {
print("\(v_int)")
// update
standard.set(2, forkey: "int")
// remove
standard.removeobject(forkey: "int")
} else {
print("not exist")
}
}
3.钥匙串(keychain)
keychain在mac上主要进行一些敏感信息存储使用 如用户名,密码,网络密码,认证令牌, wi-fi网络密码,vpn凭证等。 ios 中 keychain, 也有相同的功能实现 , 保存的信息存储在设备中, 独立于每个app沙盒之外。
当你删除app后keychain存储的数据不会删除,所以在重装app后,keychain里的数据还能使用。从ios 3.0开始,跨程序分享keychain变得可行而nsuserdefaults存储的数据会随着app而删掉。
相同的 team id 开发, 可实现多个app 共享数据。
使用keychain时苹果官方已经为我们封装好了文件keychainitemwrapper,引入即可使用。
第三方库samkeychain。。。
/// samkeychain 简单使用
func testkeychain() -> void {
let account = "479377608"
let service = "com.qq"
// 检测数据是否已存
if samkeychain.password(forservice: service, account: account) != nil {
print("keychain exist..")
} else {
// 存储
if samkeychain.setpassword("123456", forservice: service, account: account) {
print("keychain set success")
} else {
print("keychain set failed...")
}
}
}
4.归档(nskeyedarchiver)
归档是ios开发中数据存储常用的技巧,归档可以直接将对象储存成文件,把文件读取成对象。
相对于plist或者nsuserdefault形式,归档可以存储的数据类型更加多样,并且可以存取自定义对象。对象归档的文件是保密的,在磁盘上无法查看文件中的内容,更加安全。
遵守nscoding协议,并实现该协议中的两个方法。如果是继承,则子类一定要重写那两个方法。因为子类在存取的时候,会去子类中去找调用的方法,没找到那么它就去父类中找,所以最后保存和读取的时候新增加的属性会被忽略。需要先调用父类的方法,先初始化父类的,再初始化子类的。
保存数据的文件的后缀名可以随意命名。
最大的优点是:可以将复杂的对象写入文件 可以归档集合类,所以无论添加多少对象,将对象写入磁盘的方式都是一样的,不会增加工作量。
5.沙盒(sandbox)
持久化在document目录下,一般存储非机密数据。当app中涉及到电子书阅读、听音乐、看视频、刷图片列表等时,推荐使用沙盒存储,可以极大的节约用户流量,且增强了app的体验效果。
application:存放程序源文件,上架前经过数字签名,上架后不可修改。
documents: 保存应运行时生成的需要持久化的数据,itunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录。
tmp: 保存应运行时所需的临时数据,使完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。itunes同步设备时不会备份该目录。
library/caches: 保存应用运行时成的需要持久化的数据,itunes同步设备时不会备份 该目录。一般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到caches下
library/preference: 保存应用的所有偏好设置,如ios的settings(设置) 应会在该目录中查找应的设置信息。itunes同步设备时会备份该目录。
func testsandbox() -> void {
// app's home path
let path = nshomedirectory()
// document path
let documentspath = nssearchpathfordirectoriesindomains(.documentdirectory, .userdomainmask, true).first
// cache path
let cachepath = nssearchpathfordirectoriesindomains(.cachesdirectory, .userdomainmask, true).first
// library path
let librarypath = nssearchpathfordirectoriesindomains(.librarydirectory, .userdomainmask, true).first
// tmp path
let tmppath = nstemporarydirectory()
// write file
let filepath = (cachepath! as nsstring).appendingpathcomponent("test.txt")
let numbers = [1,2,3] as nsarray
if numbers.write(tofile: filepath, atomically: true) {
print("write success.")
} else {
print("write failed..")
}
// read file
guard let readnumbers = nsarray(contentsoffile: filepath) else {
print("read failed...")
return
}
print(readnumbers)
}
6.数据库(sqllite)
适合储存数据量较大的数据,一般使用fmdb等第三方库。
fmdb是ios平台的sqlite数据库框架,fmdb以oc的方式封装了sqlite的c语言api,使用起来更加面向对象,省去了很多麻烦、冗余的c语言代码,对比苹果自带的core data框架,更加轻量级和灵活,提供了多线程安全的数据库操作方法,有效地防止数据混乱。
易用性不强, 但可以存储大量数据,存储、检索大量数据非常高效;能对数据进行复杂的聚合,比使用对象执行这些操作要高效得多。
7.coredata
core data是ios5之后才出现的一个框架,它提供了对象-关系映射(orm)的功能,即能够将oc对象转化成数据,保存在sqlite数据库文件中,也能够将保存在数据库中的数据还原成oc对象。在此数据操作期间,我们不需要编写任何sql语句。
coredata本质还是讲数据存在了sqlite数据库文件,使用不是很方便。