引言

在 iOS 之网络恳求 一文中已经了解到怎么进行网络恳求,当经过网络恳求获取到数据后需求将其耐久性地存储起来时,就需求了解在iOS 开发中怎么进行耐久性地存储数据

iOS 开发中对数据进行耐久性地存储的方法首要有:本地存储数据库存储

本地存储

本地存储是指将数据存储在设备的本地文件体系上,使运用程序能够在没有互联网衔接的情况下拜访和操作数据。本地存储一般用于存储非敏感小规模的信息

UserDefaults

一种轻量级的本地存储方法,用于存储少量的键值对数据。一般用于存储运用的偏好设置和用户装备

UserDefaults是一个单例方法的类,经过.standard特点来拜访运用程序中的仅有UserDefaults 实例。这使得在整个运用程序中方便地同享和拜访数据

// 存储数据到UserDefaults
let datas = UserDefaults.standard
datas.set("JohnDoe", forKey: "Username")
datas.set(25, forKey: "Age")
datas.set(true, forKey: "IsLoggedIn")
// 读取数据从UserDefaults
let username = datas.string(forKey: "Username") 
let age = datas.integer(forKey: "Age")
let isLoggedIn = datas.bool(forKey: "IsLoggedIn")

当从UserDefaults中读取数据时,需求依据数据类型来正确读取数据。假如尝试运用不匹配的类型来读取数据,可能会导致运行时过错或回来默认值(假如设置了默认值)

经典单例方法结构

class MySingleton {
    static let shared = MySingleton()
    private init() {
        // 私有的初始化办法,确保不能在外部创立多个实例
    }
    // 这儿能够添加其他特点和办法
}

单例方法的经典结构包含一个私有的构造办法和一个公共的静态特点(或办法),用于拜访仅有实例

UserDefaults 单例方法

UserDefaults的完成方法与经典单例方法类的结构略有不同。UserDefaultsSwift 规范库供给的一个类,它是一个全局单例,其完成方法不同于传统的单例方法,而是经过Swift 规范库内部进行办理的,不需求手动完成单例方法。只需求运用UserDefaults.standard来拜访全局的单例实例,而不需求自己创立单例。这是Swift规范库为了方便数据耐久化存储而供给的一种机制,它隐藏了单例方法的杂乱性

open class UserDefaults : NSObject {
    open class var standard: UserDefaults { get }
}

Plists

全称Property Lists,一种用于存储和序列化数据的XML二进制文件格局,一般以.plist文件扩展名保存

Plists文件一般是经过键-值(key-value)的方法来存储各种类型的数据。每个数据项都有一个仅有的键(key),用于标识该数据项,然后依据键来获取对应的值。这种结构适用于存储字典、数组、字符串、整数、浮点数等多种数据类型

Plists可用于存储结构化的数据,例如装备文件、运用设置、静态数据等

// 创立一个字典,包含要保存到 Plist 文件的数据
let dataToSave: [String: Any] = [
    "Username": "JohnDoe",
    "Age": 25,
    "IsLoggedIn": true
]
// 获取 Plist 文件的 URL,一般是在运用的沙盒目录中
if let plistURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("UserData.plist") {
    do {
        // 将数据写入 Plist 文件,运用 PropertyListSerialization
        let plistData = try PropertyListSerialization.data(fromPropertyList: dataToSave, format: .xml, options: 0)
        try plistData.write(to: plistURL)
        print("Data saved to \(plistURL)")
        // 从 Plist 文件读取数据 
        let plistDataRead = try Data(contentsOf: plistURL) 
        if let dictionary = try PropertyListSerialization.propertyList(from: plistDataRead, options: [], format: nil) as? [String: Any] { 
            if let username = dictionary["Username"] as? String {
                print("Username: \(username)") 
            } 
            if let age = dictionary["Age"] as? Int { 
                print("Age: \(age)") 
            } 
            if let isLoggedIn = dictionary["IsLoggedIn"] as? Bool { 
                print("IsLoggedIn: \(isLoggedIn)") 
            }
        }
    } catch {
        print("Error writing to Plist: \(error)")
    }
}

拓展

Plist文件的数据类型:

  • 假如将文件扩展名设置为.plist,则数据将存储为XML 格局Plist文件
  • 假如将文件扩展名设置为.bplist,则数据将存储为二进制格局Plist文件

PropertyListSerialization.data(fromPropertyList: dataToSave, format: .xml, options: 0)处的format用于指定输出的格局,有.xml.binary两个值,这儿的数据格局不会影响数据写入文件时的实际格局,写入文件的数据类型是与扩展名相关

Archiver

Archiver是将目标序列化为二进制数据,并将其保存在文件中的过程,以便后续能够复原成原始目标。在iOS 开发中,能够运用NSKeyedArchiverNSKeyedUnarchiver类来进行归档反归档操作

归档的步骤

  1. 创立要归档的目标:首要,你需求创立一个自定义的类,该类需求遵循NSCoding协议,这个协议要求完成encode(with:)init(coder:)办法,以便目标能够被归档反归档
  2. 归档目标:运用NSKeyedArchiver类的实例,能够将目标归档二进制数据并将其保存到文件中
  3. 反归档目标:运用NSKeyedUnarchiver类的实例,能够从文件中读取归档数据,并将其解析原始目标
1. 创立要归档的目标
class Person: NSObject, NSCoding {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    // 完成NSCoding协议的办法
    required init?(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObject(forKey: "name") as! String
        self.age = aDecoder.decodeInteger(forKey: "age")
    }
    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(age, forKey: "age")
    }
}
2. 归档
let person = Person(name: "John", age: 30)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathComponent("person.archive")
do {
    let data = try NSKeyedArchiver.archivedData(withRootObject: person, requiringSecureCoding: false)
    try data.write(to: archiveURL)
    print("Person object archived successfully.")
} catch {
    print("Error archiving person object: \(error)")
}
3. 反归档
do {
    let data = try Data(contentsOf: archiveURL)
    if let loadedPerson = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? Person {
        print("Loaded person: \(loadedPerson.name), Age: \(loadedPerson.age)")
    } else {
        print("Failed to unarchive person object.")
    }
} catch {
    print("Error loading person object: \(error)")
}

数据库存储

数据库存储是指将数据存储在结构化数据库中,以便有效地查询、检索和办理数据。这种方法适用于需求大规模数据存储杂乱查询的情况,例如运用程序中的用户数据、购物车数据等

CoreData:苹果供给的一个高档耐久性结构,供给目标联系映射(ORM)功用,适用于杂乱的数据模型

SQLite:轻量级嵌入式联系型数据库,适用于杂乱的数据结构和查询需求

第三方数据库:运用第三方数据库解决计划,如RealmFirebase Realtime DatabaseCouchbase Lite

耐久化存储计划比照

UserDefaults 和 Plists 比照

相似之处

  1. 键-值存储: PlistUserDefaults都采用了键-值(key-value)的存储方法,其中每个数据项都有一个仅有的键用于标识
  2. 支持多种数据类型: 两者都支持存储多种数据类型,包含字符串、整数、浮点数、数组、字典等
  3. 耐久性存储: PlistUserDefaults都支持将数据耐久性地存储在设备上,以便在运用程序从头启动后保存数据

关键差异

  1. 存储位置: Plist一般是存储在运用的沙盒目录中的文件,能够轻松地创立、读取和修改;UserDefaults则是一个键值对存储体系,运用更高档的 API进行拜访
  2. 数据规模: Plist一般用于存储较大或结构化的数据;UserDefaults一般用于存储运用的用户设置和轻量级数据
  3. 拜访方法: Plist需求手动读取和写入,一般需求运用PropertyListSerialization API进行操作;UserDefaults则供给了更高档别的 API,使数据的读取和写入愈加方便

Plists 和 Archiver 比照

  • Archiver:适用于保存自定义目标杂乱数据模型运用状态信息等需求保存目标类型信息的场景。归档能够将整个目标图保存到文件中,以便康复目标的状态
  • Plists:适用于保存简单的数据结构,如键-值对、装备信息、用户偏好设置等。Plists不适用于保存自定义目标,由于它不会保存目标的类信息

总之,PlistArchiver都能够保存二进制数据,但是Plist不具备主动解析并复原自定义目标的功用,而归档(Archiver)会保存目标的类信息,使康复愈加容易

拓展

open 和 public 关键字

openpublic 是Swift中的拜访控制关键字,它们用于控制类、结构体、函数、特点等成员的可见性和拜访权限。它们之间的首要差异在于拜访等级和承继性:

  1. open 运用open关键字润饰的成员具有最高档别的拜访权限,对于其他模块(结构或库)来说是可见的,并且能够被承继。这意味着其他模块能够扩展和承继open成员。一般,open用于创立可扩展的公共接口,以便其他开发者能够承继和扩展
  2. public 运用public关键字润饰的成员也对其他模块可见,但不具有承继性。这意味着其他模块能够拜访public成员,但不能承继或重写

沙盒目录

沙盒目录(Sandbox Directory)iOS 运用程序私有文件体系空间,每个iOS 运用都有自己的独立沙盒目录,用于存储运用程序的数据和文件。沙盒目录的概念是为了确保运用程序之间的阻隔性安全性,防止一个运用程序拜访其他运用程序的数据或文件

iOS 的文件体系会依据运用程序包标识符为每个运用程序创立一个独立的沙盒目录。这意味着不同运用程序的沙盒目录是相互阻隔的,一个运用程序无法直接拜访另一个运用程序的沙盒目录内的文件

沙盒目录包含的首要文件夹

  1. Documents 目录: 用于存储用户生成的文件,例如文档、照片、视频等。这些文件会在运用程序备份时被包含在备份中,并能够经过iCloud同享
  2. Library 目录: 该目录包含两个子目录

    • Caches 目录: 用于存储能够从头生成的临时数据,例如缓存文件。这些文件不会在运用程序备份时被包含在备份中,由于它们能够随时从头生成
    • Preferences 目录: 用于存储运用程序的偏好设置,一般以plist 文件的方法存在
  3. tmp 目录: 用于存储临时文件,这些文件不会被运用程序备份,且在运用程序退出后可能会被删除
  4. 运用程序包目录: 包含了运用程序的可执行文件资源文件,一般不允许在运行时修改这个目录中的文件
// 获取路径
// for: .documentDirectory, .libraryDirectory, .cachesDirectory, .preferencePanesDirectory
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first{}

小结

关于iOS 开发中关于数据耐久化部分,首要是以本地存储数据为主,比照说明晰UserDefaultsPlistsArchiver这三种本地存储的方法;对于数据库存储仅是做了简要概述,感兴趣能够深化了解,后面假如有用到也会更新相关文章的~~