【问题标题】:Where to create and open the SQLite Database and it's tables in Swift Storyboard在哪里创建和打开 SQLite 数据库及其在 Swift Storyboard 中的表
【发布时间】:2022-11-28 00:49:04
【问题描述】:

我目前正在通过 import sqlite3 使用 SQLite 开发一个 iOS 应用程序。 我关注了 Kodeco 的 SQLite With Swift Tutorial: Getting Started - 但我遇到了一些问题,因为他们正在使用游乐场。

我在哪里创建数据库文件和表?

public class SQLiteDatabase {

    public static var currentAccount = Account(id: -1, email: "", name: "", lastname: "", gender: "", birthday: Date(), creationDate: Date())
    public static let pathExtension = "xPose.sqlite"
    public static var path: String!
    
    private let dbPointer: OpaquePointer?
    private init(dbPointer: OpaquePointer?) {
        self.dbPointer = dbPointer
    }
    
    deinit {
        sqlite3_close(dbPointer)
    }
    
    fileprivate var errorMessage: String {
        if let errorPointer = sqlite3_errmsg(dbPointer) {
            let errorMessage = String(cString: errorPointer)
            return errorMessage
        } else {
            return "No error message provided from sqlite."
        }
    }
    
    func enableForeignKeys() {
        if sqlite3_exec(dbPointer, "PRAGMA foreign_keys = ON", nil, nil, nil) != SQLITE_OK {
            let err = String(cString: sqlite3_errmsg(dbPointer))
                print("error attempting to enable foreign keys: \(err)")
            }
    }
    
    func createFile() {
        do {
            let url = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(SQLiteDatabase.pathExtension)
            SQLiteDatabase.path = url.absoluteString
            print("File created")
        }
        catch {
            print("Error creating file")
        }
    }
    
    func createTables() {
        do {
            try createTable(table: Account.self)
            try createTable(table: Measurement.self)
            try createTable(table: Posture.self)
            try createTable(table: Vital.self)
            try createTable(table: Mood.self)
        } catch {
            print("Failed to create Tables")
        }
    }
    
    // Open the databse
    static func open(path: String) throws -> SQLiteDatabase {
        var db: OpaquePointer?
        
        if sqlite3_open(path, &db) == SQLITE_OK {
            return SQLiteDatabase(dbPointer: db)
        } else {
            defer {
                if db != nil {
                    sqlite3_close(db)
                }
            }
            if let errorPointer = sqlite3_errmsg(db) {
                let message = String(cString: errorPointer)
                throw SQLiteError.OpenDatabase(message: message)
            } else {
                throw SQLiteError.OpenDatabase(message: "No error message provided from sqlite.")
            }
        }
    }
    
    func prepareStatement(sql: String) throws -> OpaquePointer? {
        var statement: OpaquePointer?
        guard sqlite3_prepare_v2(dbPointer, sql, -1, &statement, nil) == SQLITE_OK else {
            throw SQLiteError.Prepare(message: errorMessage)
        }
        return statement
    }
    
    func createTable(table: SQLTable.Type) throws {
        let createTableStatement = try prepareStatement(sql: table.createStatement)
        defer {
            sqlite3_finalize(createTableStatement)
        }
        
        guard sqlite3_step(createTableStatement) == SQLITE_DONE else {
            throw SQLiteError.Step(message: errorMessage)
        }
        print ("\(table) table created.")
    }

我尝试将它放入私有 init 方法中,但每次我尝试打开数据库时它都会尝试创建新文件和表,并且目录中没有创建数据库文件。

【问题讨论】:

    标签: swift xcode sqlite


    【解决方案1】:

    在调用sqlite3_open之前,您需要查看path的数据库文件是否存在。如果它不存在,那么你想在打开数据库文件后调用createTables

    通过这样做,一切都在您第一次尝试打开数据库时设置好了。

    是这样的:

    // Open the databse
    static func open(path: String) throws -> SQLiteDatabase {
        var db: OpaquePointer?
        
        let exists = FileManager.default.fileExists(atPath: path)
        if sqlite3_open(path, &db) == SQLITE_OK {
            if !exists {
                createTables()
            }
            return SQLiteDatabase(dbPointer: db)
        } else {
            defer {
                if db != nil {
                    sqlite3_close(db)
                }
            }
            if let errorPointer = sqlite3_errmsg(db) {
                let message = String(cString: errorPointer)
                throw SQLiteError.OpenDatabase(message: message)
            } else {
                throw SQLiteError.OpenDatabase(message: "No error message provided from sqlite.")
            }
        }
    }
    

    您只需要在您的应用程序每次启动时调用一次open

    【讨论】:

      猜你喜欢
      • 2017-02-25
      • 2011-11-17
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-02
      • 1970-01-01
      相关资源
      最近更新 更多