error Domain = FMDatabase Code = 8“尝试编写只读数据库”

时间:2017-10-27 16:46:05

标签: ios swift xcode sqlite

我正在使用FMDatabase库来使用预备数据库sqlite。

我收到了这个错误:

Error Domain=FMDatabase Code=8 "attempt to write a readonly database" UserInfo={NSLocalizedDescription=attempt to write a readonly database}
2017-10-27 19:59:10.983238+0330 kashanmap[417:63718] Unknown error calling sqlite3_step (8: attempt to write a readonly database) eu
2017-10-27 19:59:10.983473+0330 kashanmap[417:63718] DB Query: insert into LocationInfoFa 

这是我的班级:

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 openDatabase() {

        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;
        }
    }

    func closeDatabase() {
        if (database != nil) {
            database.close()
        }
    }

我的数据库路径:

enter image description here

我的疑问:

do {
        let db = database

        let q = try db?.executeUpdate("insert into \(table) (catid,subcat_id,id,subcat_title,title,description,lat,lon,takhfif,images,wifi,apple_health,wc,full_time,pos,work_hours,phone,mobile,fax,website,email,address,facebook,instagram,linkedin,telegram,googleplus,twitter,publish,feature,manager,city,rating_sum,rate_count,lastip,parking,isMallID,mallID,discount_images,price_images,newProduct_images,services_images,order_online,out_upon,cat_title,cat_icon,last_modify,item_logo,cat_logo,rate_sum1,rate_sum2,rate_sum3,rate_count1,rate_count2,rate_count3,rate_title1,rate_title2,rate_title3,rate_enable,installments_text,installments_image) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", values:[ catid,subcat_id,id,subcat_title,title,description,lat,lon,takhfif,images,wifi,apple_health,wc,full_time,pos,work_hours,phone,mobile,fax,website,email,address,facebook,instagram,linkedin,telegram,googleplus,twitter,publish,feature,manager,city,rating_sum,rate_count,lastip,parking,isMallID,mallID,discount_images,price_images,newProduct_images,services_images,order_online,out_upon,cat_title,cat_icon,last_modify,item_logo,cat_logo,rate_sum1,rate_sum2,rate_sum3,rate_count1,rate_count2,rate_count3,rate_title1,rate_title2,rate_title3,rate_enable,installments_text,installments_image])

    } catch {
        print("\(error)")
    }

堆栈溢出有一些解决方案,但它们不被接受为真正的答案。

updated2

我收到了这个错误:

DB does not exist in documents folder

我的代码:

   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")

        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;
        }
    }

1 个答案:

答案 0 :(得分:0)

您正面临此错误,因为您正尝试在捆绑目录中编写(更新) .db 文件,该目录允许:

  

<强> AppName.app:

     

这是应用程序的捆绑包。该目录包含应用程序和所有   它的资源。 您无法写入此目录。阻止   篡改,bundle目录在安装时签名。   写入此目录会更改签名并阻止您的应用程序   从发射。但是,您可以获得对任何的只读访问权限   应用包中存储的资源

     

<子> File System Basics - Table 1-1: Commonly used directories of an iOS app

如果您的目标是更新文件,您应该实现复制的逻辑 - 如果它尚未被复制到文档中目录,因此您可以使用复制的文件读/写事务。

备注对于iOS 11及更高版本,您可能希望将数据库文件复制到 Application Support 目录中,如果您不想让我们看到它们通过 Files iOS应用导航到您的应用时最终用户。有关详细信息,请查看iOS Storage Best Practices Apple视频会话。

您注意到此逻辑应该应用于应用主程序包中的任何文件,例如它也是applicable for JSON files