我在 iOS 应用程序的 Xcode 中实现 SQLite 时遇到不同的问题。
我用: Xcode 16 Swift 6.0(SwiftUI、基础、SQLite3) iOS 18.0
我有包含数据的 SQLite.sqlite 文件,我只需要从数据库中读取数据。 稍后我可能需要实现最著名的元素。
是否有任何有用的示例如何连接、获取所有数据并传递给视图。带搜索选项。
这里的解决方案是什么?
我有下一个代码:
DataModel.swift
struct DataModel: Identifiable {
let value1: Int
let value2: Int
let value3: String
let value4: String
let value5: Int
}
DBManager.swift
import Foundation
import SQLite3
class DBManager {
var db: OpaquePointer?
let dbName: String = "dbErg2024.sqlite"
init() {
openDatabase()
closeDatabase()
fetchAllData()
}
func openDatabase() {
// let fileURL = try! FileManager.default
// .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
// .appendingPathComponent(dbName)
// let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(dbName)
let dbFile = Bundle.main.url(forResource: dbName, withExtension: nil)!
if sqlite3_open(dbFile.path, &db) != SQLITE_OK {
print("Error opening database")
} else {
print("Database opened successfully at \(dbFile.path)")
}
}
func fetchAllData() -> [DataModel] {
var result: [DataModel] = []
let queryStatementString = "SELECT * FROM tableOfMyDB;"
var queryStatement: OpaquePointer?
if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
while sqlite3_step(queryStatement) == SQLITE_ROW {
let value1 = sqlite3_column_int(queryStatement, 0)
let value2 = sqlite3_column_int(queryStatement, 1)
let value3 = String(cString: sqlite3_column_text(queryStatement, 2))
let value4 = String(cString: sqlite3_column_text(queryStatement, 3))
let value5 = sqlite3_column_int(queryStatement, 4)
result.append(DataModel(value1: Int(value1), value2: Int(value2), value3: value3, value4: value4, value5: Int(value5)))
}
}else {
print("Error preparing query statement")
}
sqlite3_finalize(queryStatement)
return result
}
func closeDatabase() {
sqlite3_close(db)
}
}
ViewModel.swift
import Foundation
import Combine
class DataViewModel: ObservableObject {
@Published var data: [DataModel] = []
@Published var searchText = ""
private var dbManager = DBManager()
init() {
loadData()
}
func loadData() {
data = dbManager.fetchAllData()
}
var filteredData: [DataModel] {
if searchText.isEmpty {
return data
} else {
return data.filter { $0.value4.contains(searchText) || $0.value3.contains(searchText) }
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = DataViewModel()
var body: some View {
VStack {
TextField("Search...", text: $viewModel.searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
List(viewModel.filteredData) { item in
VStack(alignment: .leading) {
Text("Name: \(item.value4)")
Text("Guide: \(item.value3)")
}
}
}
.navigationTitle("Data List")
}
}
#Preview {
ContentView()
}
上面的代码有什么解决办法吗?
在
DBManager.swift
而不是这个:
init() {
openDatabase()
closeDatabase()
fetchAllData()
}
使用这个:
init() {
openDatabase()
fetchAllData()
}
deinit {
closeDatabase()
}
它使数据库连接保持打开状态,直到对象(DBManager)耗尽内存。我还建议通过参与者隔离、nslock 等针对竞争条件提供一些保护。