You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 5环境下SQLite数据库的实现方法及完整示例

Swift 5 实现 SQLite 本地数据库存储

我们可基于系统自带的 SQLite3 框架实现无第三方依赖的本地数据库操作,全流程分为数据模型定义、数据库逻辑封装、UI 展示三个核心环节,具体实现如下:

1. 定义本地数据模型 PersonModel

用于映射数据库表的单行数据,实现数据库原始值与内存对象的双向转换

import Foundation

class PersonModel {
    // 对应数据库表的三个字段
    var name: String = ""
    var age: Int = 0
    var id: Int = 0
    
    // 初始化方法,用于把数据库读取到的原始值绑定为模型对象
    init(name: String, age: Int, id: Int) {
        self.name = name
        self.age = age
        self.id = id
    }
}

2. 封装数据库操作工具类 DBHelper

统一管理数据库连接、建表、增删查等所有核心数据操作逻辑
注意:SQLite3 为系统内置 C 接口,不需要通过包管理工具引入,直接导入模块即可使用

import SQLite3

class DBHelper {
    // 数据库文件名,存储在沙盒文档目录下
    let dbPath: String = "myDb.sqlite"
    // SQLite 数据库操作句柄
    var db: OpaquePointer?
    
    init() {
        // 初始化时自动打开数据库连接、创建对应数据表
        db = openDatabase()
        createTable()
    }

    // 打开数据库连接
    func openDatabase() -> OpaquePointer? {
        // 获取沙盒文档目录的系统路径
        let fileURL = try! FileManager.default.url(
            for: .documentDirectory,
            in: .userDomainMask,
            appropriateFor: nil,
            create: false
        ).appendingPathComponent(dbPath)
        
        var db: OpaquePointer? = nil
        // 调用 SQLite 原生接口打开数据库
        if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
            print("打开数据库失败")
            return nil
        } else {
            print("数据库连接成功,路径:\(dbPath)")
            return db
        }
    }

    // 创建数据表
    func createTable() {
        // 建表SQL:不存在person表则自动创建,含id、name、age三个字段
        let createTableString = "CREATE TABLE IF NOT EXISTS person(Id INTEGER PRIMARY KEY, name TEXT, age INTEGER);"
        var createTableStatement: OpaquePointer? = nil
        
        // 预处理SQL语句
        if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
            // 执行预处理好的SQL
            if sqlite3_step(createTableStatement) == SQLITE_DONE {
                print("person 数据表创建成功")
            } else {
                print("person 数据表创建失败")
            }
        } else {
            print("建表SQL语句预处理失败")
        }
        // 释放语句句柄,避免内存泄漏
        sqlite3_finalize(createTableStatement)
    }
    
    // 插入单条数据
    func insert(id: Int, name: String, age: Int) {
        // 插入前先校验同id的记录是否已存在,避免重复写入
        let personList = read()
        for person in personList {
            if person.id == id {
                return
            }
        }
        
        let insertStatementString = "INSERT INTO person (Id, name, age) VALUES (?, ?, ?);"
        var insertStatement: OpaquePointer? = nil
        
        if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
            // 把参数绑定到SQL语句的占位符位置
            sqlite3_bind_int(insertStatement, 1, Int32(id))
            sqlite3_bind_text(insertStatement, 2, (name as NSString).utf8String, -1, nil)
            sqlite3_bind_int(insertStatement, 3, Int32(age))
            
            // 执行插入操作
            if sqlite3_step(insertStatement) == SQLITE_DONE {
                print("数据插入成功")
            } else {
                print("数据插入失败")
            }
        } else {
            print("插入SQL语句预处理失败")
        }
        sqlite3_finalize(insertStatement)
    }

    // 读取全量数据
    func read() -> [PersonModel] {
        let queryStatementString = "SELECT * FROM person;"
        var queryStatement: OpaquePointer? = nil
        var personList: [PersonModel] = []
        
        if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
            // 循环读取每一行返回的结果
            while sqlite3_step(queryStatement) == SQLITE_ROW {
                let id = sqlite3_column_int(queryStatement, 0)
                // 将C接口返回的文本值转换为Swift字符串
                let name = String(cString: sqlite3_column_text(queryStatement, 1))
                let age = sqlite3_column_int(queryStatement, 2)
                
                // 把原始值组装为模型对象加入返回数组
                personList.append(
                    PersonModel(name: name, age: Int(age), id: Int(id))
                )
                print("查询结果:\(id) | \(name) | \(age)")
            }
        } else {
            print("查询SQL语句预处理失败")
        }
        sqlite3_finalize(queryStatement)
        return personList
    }
    
    // 根据id删除指定数据
    func deleteByID(id: Int) {
        let deleteStatementString = "DELETE FROM person WHERE Id = ?;"
        var deleteStatement: OpaquePointer? = nil
        
        if sqlite3_prepare_v2(db, deleteStatementString, -1, &deleteStatement, nil) == SQLITE_OK {
            sqlite3_bind_int(deleteStatement, 1, Int32(id))
            if sqlite3_step(deleteStatement) == SQLITE_DONE {
                print("数据删除成功")
            } else {
                print("数据删除失败")
            }
        } else {
            print("删除SQL语句预处理失败")
        }
        sqlite3_finalize(deleteStatement)
    }
}

3. 视图层数据展示

将数据库读取到的数据集通过 UITableView 渲染到界面上

import UIKit

class HomeController: UIViewController {
    // 绑定Storyboard/XIB上的表格视图
    @IBOutlet weak var personTableView: UITableView!
    // 存储从数据库读取到的人员数据集
    var persons: [PersonModel] = []
    // 初始化数据库工具实例
    var db: DBHelper = DBHelper()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 插入测试数据到数据库
        db.insert(id: 1, name: "Bilal", age: 24)
        db.insert(id: 2, name: "Bosh", age: 25)
        db.insert(id: 3, name: "Thor", age: 23)
        db.insert(id: 4, name: "Edward", age: 44)
        db.insert(id: 5, name: "Ronaldo", age: 34)
        
        // 从数据库读取最新数据
        persons = db.read()
        // 刷新表格展示内容
        personTableView.reloadData()
    }
}

// 实现表格视图的数据源与代理方法
extension HomeController: UITableViewDelegate, UITableViewDataSource {
    // 返回表格总行数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return persons.count
    }
    
    // 配置表格单元格
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let identifier = "PersonCell"
        var cell: PersonCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? PersonCell
        // 单元格未注册时,从XIB加载并完成注册
        if cell == nil {
            tableView.register(
                UINib(nibName: "PersonCell", bundle: nil),
                forCellReuseIdentifier: identifier
            )
            cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? PersonCell
        }
        
        // 给单元格上的文本标签赋值
        cell.idLabel.text = "\(persons[indexPath.row].id)"
        cell.ageLabel.text = "\(persons[indexPath.row].age)"
        cell.nameLabel.text = "\(persons[indexPath.row].name)"
        
        return cell
    }
    
    // 设置单元格高度
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
}

内容的提问来源于 stack exchange,提问作者 Santosh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 18:15:02