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
相关产品推荐
相关产品推荐

