iOS Swift 数据管理完整指南

iOS Swift 数据管理体系
│
├── 1、内存存储 (App关闭数据丢失)
│   ├── @State - 视图内部状态
│   ├── @StateObject - 视图模型
│   └── 单例模式 - 全局数据
│
├── 2、本地持久化存储 (App关闭数据保留)
│   ├── @AppStorage - 简单设置
│   ├── UserDefaults - 键值存储
│   ├── 文件存储 - 文档数据
│   ├── SwiftData - 现代数据库
│   └── SQLite - 关系型数据库
│
└── 3、云端存储
    ├── CloudKit - 苹果官方后端服务
    └── 自建服务器 - 自定义后端服务

1、内存存储

数据保存在设备的内存( RAM )中,当APP关闭或设备重启时,这些数据会丢失。

特点:内存存储的访问速度极快,适合存储临时数据和运行时状态

1.1、@State - 视图内部状态管理

@State 是 SwiftUI 中最基本的状态管理属性包装器,用于管理单个视图的内部状态。它适用于简单的值类型数据,如字符串、整数、布尔值等。

import SwiftUI

struct LoginView: View {
    // @State 用于管理视图内部的状态,数据保存在内存中
    // 当App关闭时,这些数据会丢失
    @State private var username: String = ""       // 存储用户名输入
    @State private var password: String = ""       // 存储密码输入  
    @State private var rememberMe: Bool = false    // 存储记住我选项状态
    
    var body: some View {
        Form {
            // 文本输入框绑定到username状态
            TextField("用户名", text: $username)
                .onChange(of: username) { newValue in
                    // 监听用户名变化并打印日志
                    print("🧠 @State - 用户名更新: \(newValue)")
                }
            
            // 密码输入框绑定到password状态
            SecureField("密码", text: $password)
            
            // 开关绑定到rememberMe状态
            Toggle("记住我", isOn: $rememberMe)
                .onChange(of: rememberMe) { newValue in
                    // 监听记住我状态变化
                    print("🧠 @State - 记住我状态: \(newValue)")
                }
            
            // 登录按钮
            Button("登录") {
                // 点击登录按钮时的处理逻辑
                print("🧠 @State - 登录操作,用户名: \(username)")
            }
        }
    }
}

1.2、@StateObject - 视图级别状态管理

@StateObject 用于 SwiftUI 中管理更复杂的状态,它适用于复杂的引用类型数据。

import SwiftUI

// ObservableObject协议允许对象被SwiftUI观察,当@Published属性变化时更新视图
class UserSession: ObservableObject {
    // @Published属性会在值改变时通知所有观察者
    @Published var isLoggedIn: Bool = false        // 登录状态
    @Published var userProfile: UserProfile?       // 用户资料
    
    func login(username: String, password: String) {
        // 登录方法,模拟登录过程
        print("🧠 @StateObject - 开始登录: \(username)")
        
        // 模拟网络请求延迟
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.isLoggedIn = true
            self.userProfile = UserProfile(name: username)
            print("🧠 @StateObject - 登录成功")
        }
    }
}

// 用户资料数据模型
struct UserProfile {
    let name: String
    var lastLogin: Date = Date()   // 默认值为当前时间
}

1.3、单例模式 - 全局应用状态

整个App共享,生命周期与App一致

class AppSettings {
    // 静态常量shared是单例实例,整个App中只有这一个实例
    static let shared = AppSettings()
    
    // 全局应用设置,所有视图都可以访问
    var theme: String = "light"    // 应用主题
    var language: String = "zh"    // 应用语言
    
    // 私有初始化方法,防止外部创建新的实例
    private init() {
        print("🧠 单例模式 - AppSettings初始化")
    }
    
    func updateTheme(_ newTheme: String) {
        // 更新主题方法
        theme = newTheme
        print("🧠 单例模式 - 主题更新为: \(newTheme)")
    }
}

2、本地持久化存储

本地持久化存储将数据保存在设备的文件系统中,即使应用程序关闭或设备重启,数据也不会丢失。适合存储用户设置、应用配置和重要业务数据。

2.1、@AppStorage - 简单设置存储

@AppStorage 是 SwiftUI 提供的属性包装器,它封装了 UserDefaults 的使用,让持久化存储变得非常简单直观。

特点:
1、使用简单,类似 @State
2、自动持久化到 UserDefaults
3、支持基本数据类型
4、与 SwiftUI 深度集成

使用场景:
用户偏好设置、简单的应用配置

import SwiftUI

struct SettingsView: View {
    // @AppStorage自动将数据保存到UserDefaults,App关闭后数据仍然存在
    // "username"是存储的键名,"默认用户"是默认值
    @AppStorage("username") private var username = "默认用户"
    @AppStorage("isDarkMode") private var isDarkMode = false
    @AppStorage("notificationEnabled") private var notificationEnabled = true
    
    var body: some View {
        Form {
            // 文本输入框,输入的内容会自动保存到UserDefaults
            TextField("用户名", text: $username)
                .onChange(of: username) { newValue in
                    // 监听用户名变化,数据会自动持久化
                    print("💾 @AppStorage - 用户名保存: \(newValue)")
                }
            
            // 开关控件,状态会自动保存
            Toggle("深色模式", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { newValue in
                    print("💾 @AppStorage - 深色模式: \(newValue)")
                }
            
            // 通知开关
            Toggle("消息通知", isOn: $notificationEnabled)
        }
        .onAppear {
            // 视图显示时打印当前设置
            print("💾 @AppStorage - 加载设置: 用户名=\(username), 深色模式=\(isDarkMode)")
        }
    }
}
2.2、UserDefaults - 传统的键值存储

UserDefaults 是 Foundation 框架提供的轻量级数据持久化方案,以键值对的形式存储数据。

需要自己管理数据存取,稍复杂一些。

特点:
1、支持基本数据类型和集合
2、线程安全
3、自动序列化/反序列化
4、底层使用 Property List 格式

使用场景:
应用配置信息、用户设置和偏好、小量的结构化数据、简单的缓存数据

class UserDefaultsManager {
    // 单例模式,确保只有一个UserDefaults管理器
    static let shared = UserDefaultsManager()
    
    // UserDefaults.standard是系统提供的键值存储
    private let defaults = UserDefaults.standard
    
    func saveUserProfile(name: String, age: Int, email: String) {
        // 创建用户资料字典
        let profile: [String: Any] = [
            "name": name,           // 姓名
            "age": age,             // 年龄
            "email": email,         // 邮箱
            "lastUpdated": Date()   // 最后更新时间
        ]
        
        // 将字典保存到UserDefaults
        defaults.set(profile, forKey: "userProfile")
        // 强制立即保存到磁盘
        defaults.synchronize()
        print("💾 UserDefaults - 用户资料保存成功: \(name)")
    }
    
    func loadUserProfile() -> [String: Any]? {
        // 从UserDefaults读取用户资料
        guard let profile = defaults.dictionary(forKey: "userProfile") else {
            print("💾 UserDefaults - 未找到用户资料")
            return nil
        }
        print("💾 UserDefaults - 加载用户资料: \(profile)")
        return profile
    }
}
2.3、文件存储 - 文档和自定义数据

直接使用文件系统来存储数据,提供最大的灵活性和控制力。

特点:
1、完全控制存储格式
2、支持大文件存储
3、需要手动管理文件路径
4、可以存储任意类型的数据

使用场景:
1、用户文档和文件
2、图片、音频、视频等媒体文件
3、大量的结构化数据
4、需要自定义格式的数据

class FileStorageManager {
    static let shared = FileStorageManager()
    
    // 获取应用文档目录的URL
    private var documentsURL: URL {
        // documentDirectory是保存用户文档的目录
        FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    }
    
    func saveTextToFile(_ text: String, filename: String) -> Bool {
        // 创建文件完整路径
        let fileURL = documentsURL.appendingPathComponent(filename)
        
        do {
            // 将文本写入文件,atomically:true确保写入操作的原子性
            try text.write(to: fileURL, atomically: true, encoding: .utf8)
            print("💾 文件存储 - 文本保存成功: \(filename)")
            return true
        } catch {
            // 处理写入错误
            print("💾 文件存储 - 保存失败: \(error)")
            return false
        }
    }
    
    func readTextFromFile(filename: String) -> String {
        // 创建文件完整路径
        let fileURL = documentsURL.appendingPathComponent(filename)
        
        // 尝试读取文件内容,如果失败返回空字符串
        guard let content = try? String(contentsOf: fileURL) else {
            print("💾 文件存储 - 文件不存在: \(filename)")
            return ""
        }
        print("💾 文件存储 - 文件读取成功: \(filename)")
        return content
    }
}
2.4、SwiftData - 现代数据库

SwiftData 是 Apple 在 iOS 17 中推出的现代数据持久化框架,它提供了声明式的 API 和强大的类型安全。

特点:
1、Swift 原生语法
2、编译时类型安全
3、自动数据迁移
4、深度 SwiftUI 集成

使用场景:
1、复杂的数据模型和关系
2、需要查询和筛选的数据
3、大量的结构化数据存储
4、需要自动迁移的数据模型

import SwiftData

// @Model宏用于定义数据模型,SwiftData会自动管理持久化
@Model
class Note {
    var title: String       // 笔记标题
    var content: String     // 笔记内容
    var createdAt: Date     // 创建时间
    var isFavorite: Bool    // 是否收藏
    
    init(title: String, content: String) {
        self.title = title
        self.content = content
        self.createdAt = Date()         // 设置创建时间为当前时间
        self.isFavorite = false         // 默认未收藏
        print("💾 SwiftData - 创建Note: \(title)")
    }
}

struct NotesApp: View {
    // modelContext用于执行数据库操作(增删改查)
    @Environment(\.modelContext) private var modelContext
    
    // @Query自动从数据库查询数据,sort指定排序方式
    @Query(sort: \Note.createdAt) private var notes: [Note]
    
    var body: some View {
        NavigationView {
            List(notes) { note in
                // 显示每条笔记
                VStack(alignment: .leading) {
                    Text(note.title).font(.headline)    // 标题
                    Text(note.content).font(.body)      // 内容
                }
            }
            .navigationTitle("笔记")
        }
        .onAppear {
            // 视图显示时打印笔记数量
            print("💾 SwiftData - 加载了 \(notes.count) 条笔记")
        }
    }
}
2.5、SQLite - 关系型数据库

SQLite 是一个轻量级的、嵌入式的关系型数据库,它不需要单独的服务器进程,整个数据库就是一个单独的文件。在 iOS 开发中,SQLite 是系统内置的数据库引擎。

使用场景:
1、需要复杂查询和关联的数据
2、大量结构化数据的存储
3、需要事务保证的数据操作
4、高性能读写需求的场景(相较于SwiftData性能更高

import SQLite3

class SQLiteManager {
    static let shared = SQLiteManager()
    
    // OpaquePointer是SQLite数据库的指针
    private var db: OpaquePointer?
    
    init() {
        openDatabase()      // 打开数据库连接
        createTables()      // 创建数据表
    }
    
    private func openDatabase() {
        // 构建数据库文件路径
        let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("app.db")  // 数据库文件名
        
        // 打开数据库连接
        if sqlite3_open(fileURL.path, &db) == SQLITE_OK {
            print("💾 SQLite - 数据库打开成功")
        } else {
            print("💾 SQLite - 数据库打开失败")
        }
    }
    
    private func createTables() {
        // SQL语句:创建用户表
        let createTableSQL = """
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,   -- 主键,自增
            name TEXT NOT NULL,                     -- 姓名,不能为空
            email TEXT UNIQUE NOT NULL              -- 邮箱,唯一约束
        );
        """
        
        // 执行SQL语句
        if sqlite3_exec(db, createTableSQL, nil, nil, nil) == SQLITE_OK {
            print("💾 SQLite - 用户表创建成功")
        } else {
            print("💾 SQLite - 用户表创建失败")
        }
    }
}

3、云端存储

如果希望数据不受APP卸载影响,可将数据存储在云端。

3.1、CloudKit - 苹果官方后端云服务

苹果官方提供的后端云服务

特点:
1、无服务器架构:无需管理任何服务器基础设施
2、深度集成:与 iOS/macOS 生态系统无缝协作
3、自动同步:跨设备数据自动同步
4、免费额度:每月 10GB 存储 + 50GB 传输 + 200MB 数据库

使用场景:
1、纯苹果生态应用
2、个人开发者或小团队
3、需要快速上线的项目
4、数据模型相对简单

import SwiftUI
import CloudKit

// 数据模型
struct TodoItem: Identifiable {
    let id = UUID()
    let title: String
    let recordID: CKRecord.ID?
}

class CloudKitManager: ObservableObject {
    @Published var items: [TodoItem] = []
    private let container = CKContainer.default().publicCloudDatabase
    
    // 保存到 CloudKit
    func saveItem(_ title: String, completion: @escaping (Bool) -> Void) {
        let record = CKRecord(recordType: "TodoItem")
        record["title"] = title as CKRecordValue
        
        container.save(record) { [weak self] (record, error) in
            DispatchQueue.main.async {
                if error == nil, let record = record {
                    let newItem = TodoItem(title: title, recordID: record.recordID)
                    self?.items.append(newItem)
                    completion(true)
                } else {
                    completion(false)
                }
            }
        }
    }
    
    // 从 CloudKit 查询数据
    func fetchItems() {
        let query = CKQuery(recordType: "TodoItem", predicate: NSPredicate(value: true))
        
        container.perform(query, inZoneWith: nil) { [weak self] (records, error) in
            guard let records = records, error == nil else { return }
            
            DispatchQueue.main.async {
                self?.items = records.compactMap { record in
                    guard let title = record["title"] as? String else { return nil }
                    return TodoItem(title: title, recordID: record.recordID)
                }
            }
        }
    }
}

// SwiftUI 视图
struct CloudKitView: View {
    @StateObject private var manager = CloudKitManager()
    @State private var newItemTitle = ""
    
    var body: some View {
        VStack {
            TextField("输入待办事项", text: $newItemTitle)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
            
            Button("添加") {
                manager.saveItem(newItemTitle) { success in
                    if success { newItemTitle = "" }
                }
            }
            
            List(manager.items) { item in
                Text(item.title)
            }
        }
        .onAppear {
            manager.fetchItems()
        }
    }
}
3.2、自建服务器

特点:
1、完全控制:自主选择技术栈和架构
2、跨平台支持:可为任何平台提供 API
3、功能灵活:可实现任意复杂业务逻辑
4、成本可控:按需选择云服务商和配置

使用场景:
1、需要跨平台支持(Android、Web等)
2、复杂业务逻辑需求
3、企业级应用
4、需要与第三方服务深度集成
5、团队有后端开发能力

//Swift 访问 SpringBoot 接口完整代码示例:

import Foundation

// 用户数据模型
struct User: Codable {
    let id: Int?
    let name: String
    let email: String
}

// 网络请求管理器
class ApiService {
    private let baseURL = "http://localhost:8080/api"
    
    // 获取所有用户
    func getUsers() async throws -> [User] {
        let url = URL(string: "\(baseURL)/users")!
        let (data, _) = try await URLSession.shared.data(from: url)
        return try JSONDecoder().decode([User].self, from: data)
    }
    
    // 创建用户
    func createUser(name: String, email: String) async throws -> User {
        let url = URL(string: "\(baseURL)/users")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let user = User(id: nil, name: name, email: email)
        request.httpBody = try JSONEncoder().encode(user)
        
        let (data, _) = try await URLSession.shared.data(for: request)
        return try JSONDecoder().decode(User.self, from: data)
    }
    
    // 删除用户
    func deleteUser(id: Int) async throws {
        let url = URL(string: "\(baseURL)/users/\(id)")!
        var request = URLRequest(url: url)
        request.httpMethod = "DELETE"
        
        _ = try await URLSession.shared.data(for: request)
    }
}

// 使用示例
class UserViewModel: ObservableObject {
    @Published var users: [User] = []
    private let api = ApiService()
    
    func loadUsers() {
        Task {
            do {
                let fetchedUsers = try await api.getUsers()
                await MainActor.run {
                    self.users = fetchedUsers
                }
            } catch {
                print("获取用户失败: \(error)")
            }
        }
    }
    
    func addUser(name: String, email: String) {
        Task {
            do {
                let newUser = try await api.createUser(name: name, email: email)
                await MainActor.run {
                    self.users.append(newUser)
                }
            } catch {
                print("创建用户失败: \(error)")
            }
        }
    }
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐