将数据库文件从包移动到文档文件夹 - FMDB

时间:2017-10-27 18:00:16

标签: ios swift xcode

我正在使用FMdatabase。 我想使用准备好的数据库。

我想我应该将数据库文件从bundle移动到文档文件夹。

我的代码:

import FMDB
class DatabaseManager {

    private let dbFileName = "kashanmapDB_upgrade_3-4.db"
    private var database:FMDatabase!

    let TABLE_LOCATION_FA           = "LocationInfoFa";
    let TABLE_LOCATION_EN           = "LocationInfoEn";
    let TABLE_GREAT_PEOPLE_FA       = "GreatPeopleInfoFa";
    let TABLE_GREAT_PEOPLE_EN       = "GreatPeopleInfoEn";
    let TABLE_TAGS                  = "Tags";
    let TABLE_RELATION_TAG_LOCATION = "RelationTagLocation";
    let TABLE_NECESSARY_INFORMATION = "NecessaryInformation";
    let TABLE_SLIDER_FA             = "SliderFa";
    let TABLE_SLIDER_EN             = "SliderEn";
    let DATABASE_VERSION            = 4;
    static var LANGUAGE                    = 1 ; //1:Fa , 2:En
    var utilities                   = Utilities()

    init() {
        openDatabase()

        if(utilities.getData(key: "lang") == "2")
        {
            DatabaseManager.LANGUAGE = 2
        }

    }

    func copyDatabaseIfNeeded() {
        // Move database file from bundle to documents folder

        let fileManager = FileManager.default

        let documentsUrl = fileManager.urls(for: .documentDirectory,
                                            in: .userDomainMask)

        guard documentsUrl.count != 0 else {
            return // Could not find documents URL
        }

        //let finalDatabaseURL = documentsUrl.first!.appendingPathComponent("kashanmapDB_upgrade_3-4.db")
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let finalDatabaseURL = URL(fileURLWithPath: paths).appendingPathComponent(dbFileName)

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

            let documentsURL = Bundle.main.resourceURL?.appendingPathComponent("kashanmapDB_upgrade_3-4.db")

            do {
                try fileManager.copyItem(atPath: (documentsURL?.path)!, toPath: finalDatabaseURL.path)
            } catch let error as NSError {
                print("Couldn't copy file to final location! Error:\(error.description)")
            }

        } else {
            print("Database file found at path: \(finalDatabaseURL.path)")
        }

    }

    func openDatabase() {

        self.copyDatabaseIfNeeded()

        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let dbPath = URL(fileURLWithPath: paths).appendingPathComponent(dbFileName)

        let str_path = Bundle.main.resourceURL!.appendingPathComponent(dbFileName).path
        let database = FMDatabase(path: str_path)

        /* Open database read-only. */
        if (!(database.open(withFlags: 2))) {
            print("Could not open database at \(dbPath).")
        } else {
            print("opened database")
            self.database = database;
        }
    }

第一次(安装应用程序时)我收到此错误消息:

DB does not exist in documents folder

我总是得到这样的信息:

Error Domain=FMDatabase Code=8 "attempt to write a readonly database" UserInfo={NSLocalizedDescription=attempt to write a readonly database}

enter image description here

2 个答案:

答案 0 :(得分:2)

嗯......看看你的代码:

func openDatabase() {

    self.copyDatabaseIfNeeded()

    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let dbPath = URL(fileURLWithPath: paths).appendingPathComponent(dbFileName)

    let str_path = Bundle.main.resourceURL!.appendingPathComponent(dbFileName).path
    let database = FMDatabase(path: str_path)

    /* Open database read-only. */
    if (!(database.open(withFlags: 2))) {
        print("Could not open database at \(dbPath).")
    } else {
        print("opened database")
        self.database = database;
    }
}

您似乎将dbPath设置为等于文档文件夹中文件的路径,但是您尝试打开的database str_path等于Bundle路径。

也许只是改变:

let database = FMDatabase(path: str_path)

为:

let database = FMDatabase(path: dbPath)

答案 1 :(得分:1)

复制数据库后,您正尝试从捆绑包中打开数据库。打开Documents文件夹中的那个。如果您在处理缺失数据库的if语句中定义了包URL(如下所示),则不会意外地抓取错误的数据库。

顺便说一下,Apple更加关注存储在Documents文件夹中的内容(参见iOS Storage Best Practices)。您可能希望使用“应用程序支持”文件夹。

let fileURL = try! FileManager.default
    .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    .appendingPathComponent("test.sqlite")

let fileExists = (try? fileURL.checkResourceIsReachable()) ?? false
if !fileExists {
    let bundleURL = Bundle.main.url(forResource: "test", withExtension: "sqlite")!
    try! FileManager.default.copyItem(at: bundleURL, to: fileURL)
}

let db = FMDatabase(url: fileURL)
guard db.open() else {
    print("unable to open")
    return
}