在 SwiftUI 中,有多种常用的数据存储方式,根据需求的不同,可以选择适合的存储方案。以下是几种常用的数据存储方式: @AppStorage/UserDefaults/CoreData/File Storage/Keychain,分别来看一下他们的使用场景和区别。
1. @AppStorage 和 UserDefaults
@AppStorage 是 SwiftUI 的一个属性包装器,用于简化对 UserDefaults 的访问。适用于存储简单的数据,例如用户设置和偏好。如果@AppStorage和UserDefaults使用的是同一个key存储的数据,那么他们之间的数据是共享的,值会使用同一个。是一种简单的键值对存储,适用于存储小规模的用户设置。
@AppStorage示例:
import SwiftUI
struct ContentView: View {
@AppStorage("username") private var username: String = "Guest"
var body: some View {
VStack {
TextField("Username", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Text("Hello, \(username)!")
}
}
}
UserDefaults示例:
struct AppStorageDemo: View {
@State var userName: String?
var body: some View {
VStack(spacing: 30) {
if let userName {
Text(userName)
.font(.title)
}
Button(action: {
userName = "Daniel"
// 使用UserDefaults设置值
UserDefaults.standard.setValue(userName, forKey: "userName")
}, label: {
Text("SAVE")
.foregroundColor(.white)
.padding()
.background(Color.red)
.clipShape(Capsule())
})
}
.onAppear {
// 当页面出现的时候,加载UserDefaults里面的值
userName = UserDefaults.standard.string(forKey: "userName")
}
}
}
使用效果展示:
2. @State 和 @StateObject
@State 和 @StateObject 用于管理视图内部的状态。虽然它们通常用于临时状态,但也可以用于简单的数据存储,但是App重新启动或者页面关闭后,这些状态可能就恢复初始值了。
import SwiftUI
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button(action: {
count += 1
}) {
Text("Increment")
}
}
}
}
3. @ObservedObject 和 @EnvironmentObject
@ObservedObject 和 @EnvironmentObject 用于在视图之间共享状态对象。通常配合 ObservableObject 使用,用于管理复杂的状态和数据。但是也是临时在内存中的数据,App重启后数据就销毁了。
示例:
import SwiftUI
class UserData: ObservableObject {
@Published var username: String = "Guest"
}
struct ContentView: View {
@StateObject private var userData = UserData()
var body: some View {
VStack {
TextField("Username", text: $userData.username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Text("Hello, \(userData.username)!")
}
.environmentObject(userData)
}
}
struct AnotherView: View {
@EnvironmentObject var userData: UserData
var body: some View {
Text("Welcome, \(userData.username)!")
}
}
4. Core Data
Core Data 是一个强大的框架,用于管理对象图和持久化存储。适用于需要持久化和查询复杂数据结构的应用。
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
List {
ForEach(items) { item in
Text("Item at \(item.timestamp!, formatter: itemFormatter)")
}
.onDelete(perform: deleteItems)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
private let itemFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
return formatter
}()
5. File Storage
文件存储适用于需要存储大量数据或复杂文件(例如 JSON、图片等)的场景。
import SwiftUI
struct ContentView: View {
@State private var text: String = ""
var body: some View {
VStack {
TextField("Enter some text", text: $text)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button("Save to file") {
saveTextToFile(text)
}
}
.padding()
}
func saveTextToFile(_ text: String) {
let filename = getDocumentsDirectory().appendingPathComponent("output.txt")
do {
try text.write(to: filename, atomically: true, encoding: String.Encoding.utf8)
print("Saved to \(filename)")
} catch {
print("Failed to write to file: \(error.localizedDescription)")
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
}
6. Keychain
Keychain 适用于存储敏感数据,例如用户凭证和密码。使用 Keychain 存储数据需要导入 Security
框架并编写相应的读写函数。可以使用第三方库(例如 KeychainAccess)简化操作。
总结
在 SwiftUI 中,常用的数据存储方式包括:
@AppStorage 和 UserDefaults:用于简单、轻量级的数据存储。
@State、@StateObject、@ObservedObject 和 @EnvironmentObject:用于视图和状态管理。
Core Data:用于复杂的数据持久化和查询。
文件存储:用于存储大文件或复杂文件。
Keychain:用于存储敏感数据。
根据应用的需求选择合适的数据存储方案,有助于提升应用的性能和数据管理效率。