【问题标题】:Table not found after adding preloaded sqlite db to iOS App using Xcode使用 Xcode 将预加载的 sqlite db 添加到 iOS 应用程序后找不到表
【发布时间】:2018-09-04 01:25:52
【问题描述】:

我有一个预加载的 SQLite 数据库,名为“myDB.dms”。我想打包数据库并从应用程序中访问内容。

首先,我将数据库文件拖放到我的 Xcode ProjectNavigator 窗口中,并在提示符下单击“如果需要复制文件”。

我使用 FMDB 库来访问 SQLite DB。

我创建了一个新的数据库接口类并添加了 3 个不同的方法:

  1. openDB
  2. 复制数据库
  3. 执行查询

因为打包 DB 文件时会在 Bundle 资源文件夹中,所以我必须将文件从资源文件夹复制到目录文件夹,如下所示:

func copyDB() -> Bool {
    let fileManager = FileManager.default
    let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
    var returnStatus: Bool = false

    guard documentsUrl.count != 0 else {
        print("Could not find documents url")
        return false
    }

    let finalDatabaseURL = documentsUrl.first!.appendingPathComponent(dbFileName)

    if !((try? finalDatabaseURL.checkResourceIsReachable()) ?? false) {
        print("DB does not exist in documents folder")

        let documentsURL = Bundle.main.resourceURL?.appendingPathComponent(dbFileName)

        do {
            try fileManager.copyItem(atPath: (documentsURL?.path)!, toPath: finalDatabaseURL.path)
        } catch let error as NSError {
            print ("Couldnt copy file to final location! Error:\(error.description)")
            returnStatus = false
        }
    } else {
        print ("Database file found at path: \(finalDatabaseURL.path)")
        returnStatus = true
    }

    return returnStatus
}

下面是 OpenDatabase 的代码

func openDB() -> Bool {
    let fileManager = FileManager.default
    let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
    let dbPath = documentsUrl.first!.appendingPathComponent(dbFileName)
    let database = FMDatabase(url: dbPath)

    var returnStatus: Bool = false

    if (self.copyDB() == false) {
        returnStatus = false
    } else {
        if (!database.open(withFlags: 1)) {
            print("Could not open database at \(dbPath.absoluteString)")
            returnStatus = false
        } else {
            self.database = database
            returnStatus = true
        }
    }

    return returnStatus
}

下面是执行查询的代码

func executeQuery(queryString:String) {
    print(queryString)
    do {
        if (database.open()){
            let results:FMResultSet = try database.executeQuery(queryString, values: nil)

            if results.next() == true {
                print(results)
            }
        }
    } catch let error as NSError {
        print(error.description)
    }
}

copyDB() 和 openDB() 工作正常,但是我尝试执行Query(),出现以下错误:

Error Domain=FMDatabase Code=1 "no such table: tableName" UserInfo={NSLocalizedDescription=no such table: tableName}

【问题讨论】:

  • 猜测(抱歉不熟悉 IOS)在副本创建数据库之前打开,因此副本认为不需要做任何事情,即数据库本身存在,尽管它是空的。我建议 1) 检查文件是否存在。 2)如果文件不存在,则复制该文件。 3) 打开数据库。 4) 执行查询。
  • 你是对的。在进一步调试时,我发现该文件没有从捆绑资源复制到文档文件夹。 Bundle 中的大小为 61734912,而 Documents 中的大小为 0。任何人都可以确认我复制的方式是否正确,因为我捕获异常 Error Domain=NSCocoaErrorDomain Code=4 "The file "H1BData.dms" doesn't exist."
  • @Rookie 我正在寻找教程/文章来实现预填充的数据库,但没有得到任何帮助。你能推荐我任何关于你所做的事情的好文章吗?其他源代码。

标签: ios swift sqlite fmdb


【解决方案1】:

以下是有效的代码:

    func copyDataBase() -> Bool {
    let fileManager = FileManager.default
    var dbPath = ""

    do {
        dbPath = try fileManager.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(dbFileName).path
    } catch {
        print(error.localizedDescription)
        return false
    }

    if !fileManager.fileExists(atPath: dbPath) {
        let dbResourcePath = Bundle.main.path(forResource: "dbName", ofType: "sqlite")
        do {
            try fileManager.copyItem(atPath: dbResourcePath!, toPath: dbPath)
        } catch {
            print(error.localizedDescription)
            return false
        }
    }
    return true
}

希望对有需要的人有所帮助

【讨论】:

    【解决方案2】:
      Firstly Create FileManager Object. Get Path and check file is exist or not then copy items from db.
         func callForCopyDBAllObejct() -> Bool {
         let fileM = FileManager.default
         var dbPath = nil
    
        do {
          dbPath = try fileM.url(for: .applicationSupportDirectory, 
     in: .userDomainMask, appropriateFor: nil, create: 
       true).appendingPathComponent(dbFileName).path
       } catch {
          print(error.localizedDescription)
           return false
       }
    
         if !fileM.fileExists(atPath: dbPath) {
           let dbResourcePath = Bundle.main.path(forResource: "dbName", 
       ofType: "sqlite")
           do {
             try fileM.copyItem(atPath: dbResourcePath!, toPath: 
        dbPath)
           } catch {
            print(error.localizedDescription)
            return false
           }
       }
       return true
    

    }

    【讨论】:

    • 感谢 Sunil Kumar,这与我的答案完全相同。
    猜你喜欢
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多