“ RLMException”,原因:“从错误的线程访问了领域。”

时间:2018-08-16 14:03:06

标签: ios swift xcode multithreading realm

我需要将我的人员模型写入领域db。我从不理解这是什么意思,因为我使用的是Realm的一个实例,并且我认为我使用的是同一线程。我错了吗?

 func updatePerson(ps:personTmp){



        let db=fetchPerson()

        guard let url=URL(string: "\(address)pe?Authorization=\(db.serverToken)") else {return}

        var urlRequest=URLRequest(url: url)

        urlRequest.httpMethod="PUT"
        urlRequest.addValue("Application/Json", forHTTPHeaderField: "Content-type")

        print(ps.dictionary)
        let body = try! JSONSerialization.data(withJSONObject: ps.toJSON(), options: .prettyPrinted)

         urlRequest.httpBody=body

        URLSession.shared.dataTask(with: urlRequest) { (data, response, err) in


            if let content=data {

                let json = try! JSONSerialization.jsonObject(with: content, options: .allowFragments) as! [String:AnyObject]

                let ersonJson =  json["data"] as! AnyObject

                let tmp = Mapper<person>().map(JSONObject: ersonJson)!
                tmp.serverToken = db.serverToken

                print(tmp)

                     self.dbManager.deleteAllFromDatabase()

                            if self.dbManager.saveData(ps: tmp) {


                            }
}

这是我的

class databaseManager {


    var database:Realm
    //var shareInstance=databaseManager()

     static let share=databaseManager()
    var config = Realm.Configuration()

    init() {
        config = Realm.Configuration(

            // set a new version number, the version number must bigger than before

            // if you never set it, it's 0

            schemaVersion: 1,

            migrationBlock: { migration, oldSchemaVersion in

                if (oldSchemaVersion < 1) {
                    // do nothing
                }
        })

        // tell Realm the new config should be used

        Realm.Configuration.defaultConfiguration = config

        // open realm file and it will do auto-migration



        self.database = try! Realm()
    }




    func fetchData() ->   person {

        let nill=person()

        DispatchQueue.global(qos: .background).async {

        Realm.Configuration.defaultConfiguration = self.config

        }

        if let results =  self.database.objects(person.self).first {

            return results

        }else {

            return nill
        }



    }





    func saveData(ps: person) ->Bool  {

        var bool:Bool?



            try! self.database.write {

                if (ps.serverToken.isEmpty || ps.identityId.isEmpty) {
                    bool=false

                }else {
                    bool = true
                    self.database.add(ps, update: true)

                }

            }



        return bool!


}





    func deleteAllFromDatabase()  {



        DispatchQueue.main.async {

            try!   self.database.write {

                self.database.deleteAll()

            }

        }


    }

您能告诉我我的保存功能出了什么问题吗?我该怎么办? 如何在没有线程冲突的情况下编写模型?

1 个答案:

答案 0 :(得分:1)

使用Singleton并不意味着它将始终在同一线程上被调用...例如。

// 1. here you are likely in the main thread
URLSession.shared.dataTask(with: urlRequest) { (data, response, err) in 
   // 2. here you are in a background thread
}

您的单例(databaseManager)可能已在主线程上创建。当您处于上述第2点所述的异步函数闭包中时,您处于后台线程中。因此,如果您在后台线程中创建对象,然后将其传递给databaseManager保存,则会将在后台线程中创建的对象传递给在主线程中创建的领域实例。造成您的问题。

如果我没记错的话,您应该能够分派到闭包内的主线程并摆脱此错误:

DispatchQueue.main.async {
    let json = try! JSONSerialization.jsonObject(with: content, options: .allowFragments) as! [String:AnyObject]
    let ersonJson =  json["data"] as! AnyObject
    let tmp = Mapper<person>().map(JSONObject: ersonJson)!
    tmp.serverToken = db.serverToken

    self.dbManager.deleteAllFromDatabase()
    if self.dbManager.saveData(ps: tmp) {

    }
}