返回

将数据持久化:UserDefaults 与 SwiftUI

IOS

概述

构建应用时,我们通常会面临一个问题:应用重启后,所有的数据都被擦除了。对于有些应用来说,这没什么大不了的,比如计算器或记事本。但对于那些需要存储数据的应用来说,这显然是一个致命的缺陷。

为了解决这个问题,我们需要一种方法来将数据存储在设备上,以便在应用重启后仍能访问它们。在 SwiftUI 中,我们可以使用 UserDefaults 来实现数据持久化。

UserDefaults 简介

UserDefaults 是一个存储键值对的轻量级数据库。它可以存储各种类型的数据,包括字符串、数字、布尔值和数组。UserDefaults 是一个单例,这意味着它在整个应用程序中都是可用的。

我们可以使用 UserDefaults 来存储各种数据,例如:

  • 用户设置
  • 应用状态
  • 游戏数据
  • 缓存数据

使用 UserDefaults 存储数据

要使用 UserDefaults 存储数据,我们可以使用 UserDefaults.standard.set(_:forKey:) 方法。该方法有两个参数:第一个参数是要存储的值,第二个参数是键。

例如,我们可以使用以下代码将一个字符串存储到 UserDefaults 中:

UserDefaults.standard.set("Hello, world!", forKey: "greeting")

使用 UserDefaults 加载数据

要使用 UserDefaults 加载数据,我们可以使用 UserDefaults.standard.object(forKey:) 方法。该方法有一个参数:键。

例如,我们可以使用以下代码从 UserDefaults 中加载一个字符串:

let greeting = UserDefaults.standard.object(forKey: "greeting") as? String

如果键不存在,object(forKey:) 方法将返回 nil。

使用 UserDefaults 存储和加载数据示例

现在,我们来看一个使用 UserDefaults 存储和加载数据的示例。

假设我们有一个 SwiftUI 应用,用于管理一个待办事项列表。我们希望在应用重启后仍然能够访问待办事项列表。

我们可以使用 UserDefaults 来存储待办事项列表。首先,我们需要创建一个 ToDoItem 结构体来表示一个待办事项:

struct ToDoItem: Identifiable {
    let id = UUID()
    let title: String
    let completed: Bool
}

然后,我们需要创建一个 ToDoList 类来管理待办事项列表:

class ToDoList: ObservableObject {
    @Published var items: [ToDoItem] = []

    func save() {
        UserDefaults.standard.set(try? JSONEncoder().encode(items), forKey: "toDoList")
    }

    func load() {
        if let data = UserDefaults.standard.object(forKey: "toDoList") as? Data {
            if let items = try? JSONDecoder().decode([ToDoItem].self, from: data) {
                self.items = items
            }
        }
    }
}

ToDoList 类中,我们定义了一个 items 属性来存储待办事项列表。我们还定义了 save()load() 方法来将待办事项列表存储到 UserDefaults 和从 UserDefaults 加载待办事项列表。

save() 方法中,我们将 items 属性编码为 JSON 格式,然后将其存储到 UserDefaults 中。在 load() 方法中,我们将从 UserDefaults 中加载 JSON 数据,然后将其解码为 [ToDoItem] 数组,并将其赋值给 items 属性。

最后,我们在 ContentView 中使用 ToDoList 类来管理待办事项列表:

struct ContentView: View {
    @ObservedObject var toDoList = ToDoList()

    var body: some View {
        List {
            ForEach(toDoList.items) { item in
                Text(item.title)
            }
        }
        .onAppear {
            toDoList.load()
        }
        .onDisappear {
            toDoList.save()
        }
    }
}

ContentView 中,我们使用 @ObservedObject 属性包装器来观察 toDoList 类的变化。当 toDoList 类的 items 属性发生变化时,ContentView 也会更新。

我们还在 onAppear()onDisappear() 方法中调用 toDoList 类的 load()save() 方法来在应用启动时加载待办事项列表,并在应用退出时保存待办事项列表。

现在,我们就可以在应用重启后仍然访问待办事项列表了。