无法在 Xcode for iOS 上使用 Swift 从 SQLite 获取数据

问题描述 投票:0回答:1

我在 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()
}

上面的代码有什么解决办法吗?

ios swift xcode sqlite
1个回答
0
投票

DBManager.swift
而不是这个:

init() {
    openDatabase()
    closeDatabase()
    fetchAllData()
}

使用这个:

init() {
    openDatabase()
    fetchAllData()
}

deinit {
    closeDatabase()
}

它使数据库连接保持打开状态,直到对象(DBManager)耗尽内存。我还建议通过参与者隔离、nslock 等针对竞争条件提供一些保护。

© www.soinside.com 2019 - 2024. All rights reserved.