【问题标题】:Load data from sqlite file Swift 4.2从 sqlite 文件 Swift 4.2 加载数据
【发布时间】:2019-10-15 09:46:33
【问题描述】:

我在 sqlite 文件中有大型数据库 所以我试图直接从我的 data.sqlite 文件中访问它 但我无法访问它。我过去使用目标 C 完成了该任务

采取的步骤:

1:将data.sqlite文件拖入项目中

2:尝试通过 fmdb 访问它

输出:路径=== /var/mobile/Containers/Data/Application/557B2961-52D8-4B14-BABC-BF4829852127/Documents/data.sqlite

let documentsDirectory = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString) as String 
pathToDatabase = documentsDirectory.appending("/(databaseFileName)")

func openDatabase() -> Bool {
 print("path=== \(pathToDatabase ?? "empty")")
      if database == nil {
           if FileManager.default.fileExists(atPath: pathToDatabase) {
                database = FMDatabase(path: pathToDatabase) 
//code is not entering in that if , it should be there becasuse I already included my sqlitefile    
 } 
        if database != nil {
            if database.open() {
                return true
            }
        }
        return false
    }

【问题讨论】:

  • 显示您如何设置pathToDatabase。您是否确认您的data.sqlite 在构建应用程序时实际上被复制到应用程序的捆绑包中?
  • 让documentsDirectory = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString) as String pathToDatabase = documentsDirectory.appending("/(databaseFileName)")
  • 这需要在您的问题中,而不是在评论中。
  • 请指导我如何确认 data.sqlite 文件实际上正在被复制到应用程序包中?
  • 查看stackoverflow.com/a/51054075/1226963 了解如何检查文件的目标成员。

标签: ios swift sqlite fmdb


【解决方案1】:

我没有使用过 fmdb,但我在最近的一个项目中成功使用了 GRDB (https://github.com/groue/GRDB.swift)。通常,这些库将允许您在出现错误时检索错误代码或日志输出,这可能对解决您的问题非常有用。

与此同时,我正在使用 Swift 函数将文件名转换为完整的 Documents 用户路径:

    private static func path(for filename: String) -> String {
        let fm = FileManager.default
        let documentsDirectory = fm.urls(for: .documentDirectory, in: .userDomainMask).first
        return documentsDirectory?.appendingPathComponent(filename).absoluteString ?? filename
    }

但是请注意,作为构建的一部分包含的文件通常不会出现在您的文档中,它将是捆绑资源的一部分。在这种情况下,这段代码可能更有用:

    let path = Bundle.main.path(forResource: "mydatabase", ofType: "sqlite")

【讨论】:

    【解决方案2】:

    如果本地数据库文件不存在,请尝试将其复制到应用的文档库中。

    import FMDB
    
    class DBService {
        // MARK: Properties
        static let shared = DBService()
        var database: FMDatabase!
    
        private let fileManager = FileManager.default
        private var documentsDBPath: String
        private var resourcesDBPath: String
    
        private let databaseFileName = "data"
        private let databaseFileName = "sqlite"
    
        // MARK: Initializers
        private init() {
            documentsDBPath = try! fileManager
                .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
                .appendingPathComponent(databaseFileName)
                .appendingPathExtension(databaseFileExtension)
                .path
    
            resourcesDBPath = Bundle.main.path(forResource: databaseFileName,
                                               ofType: databaseFileExtension)!
        }
    
        // MARK: - Setup
        func isDatabaseOpen() -> Bool {
            if database == nil {
                initDatabase()
            }
    
            return database.open()
        }
    
        private func initDatabase() {
            if isFirstLaunch() {
                copyDatabase(from: resourcesDBPath, to: documentsDBPath)  
            }
    
            database = FMDatabase(path: documentsDBPath)
        }
    
        private func isFirstLaunch() -> Bool {
            return !fileManager.fileExists(atPath: documentsDBPath)
        }
    
        private func copyDatabase(from source: String, to destination: String) {
            do {
                try fileManager.copyItem(atPath: source, toPath: destination)
            } catch {
                debugPrint(error)
            }
        }
    }
    

    【讨论】:

    • 根据他的用例,复制可能合适也可能不合适。具有不变数据的数据库会浪费空间,尤其是在大数据库的情况下,如果它以只读模式使用。
    【解决方案3】:

    您的文件显然不在文档目录中,您应该在主包中访问它

    let dbUrl = Bundle.main.url(forResource: "data", withExtension: "sqlite")
    

    如果您需要将数据库复制到文档目录中,请改用以下内容

    let fileManager = FileManager.default
    let dbUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).last!.appendingPathComponent("data.sqlite")
    if !fileManager.fileExists(atPath: dbUrl.path) {
        let url = Bundle.main.url(forResource: "data", withExtension: "sqlite")!
        try? fileManager.copyItem(at: url, to: dbUrl)
    }
    

    用法

    let database = FMDatabase(url: dbUrl)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      相关资源
      最近更新 更多