Realm accessed from incorrect thread - Swift 3

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-09 03:16:51

问题


At the top of my UITableViewController is the following:

let queue = DispatchQueue(label: "background")

When a task is deleted, the following executes:

self.queue.async {
    autoreleasepool {
        let realm = try! Realm()
        realm.beginWrite()
        realm.delete(task)
        do {
            try realm.commitWrite()
        } catch let error {
            self.presentError()
        }
    } 
 }

And then I receive the error

terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.

How could I fix this?


回答1:


It seems like the write is happening on a different thread than the object was originally accessed from. You should be able to fix it by passing task's id and using that to fetch it from the database right before you do the write (inside the async block).

So at the top:

var taskId = 0  // Set this accordingly

and then something like

self.queue.async {
    autoreleasepool {
        let realm = try! Realm()
        let tempTask = // get task from Realm based on taskId
        realm.beginWrite()
        realm.delete(tempTask)
        do {
            try realm.commitWrite()
        } catch let error {
            self.presentError()
        }
    } 
 }



回答2:


We need to understand the fact Realm Objects cannot be accessed from different threads. What does this means and how to workout this issue.

First, realm objects cannot be access from different thread means, one instance of thread defined in one thread cannot be access from different thread. What we should do actually is we need to have different instance of realm instance for each thread.

For eg. let's look at following e.g. where we insert 50 records in database asynchronously in background thread upon button click and we add notification block in main thread to update the no of people in count label. Each thread (main and background ) have its own instance of realm object to access Realm Database. Because Realm Database achieves thread safety by making instances of Realm thread-confined.

class Person: Object {
    dynamic var name = ""
    convenience init(_ name: String) {
        self.init()
        self.name = name
    }
}


override func viewDidAppear(_ animated: Bool) {
    let realmMain = try!  Realm ()
    self.people = realmMain.objects(Person.self)
    self.notification = self.people?.addNotificationBlock{ [weak self] changes in
        print("UI update needed")
        guard let countLabel = self?.countLabel else {
            return
        }
        countLabel.text = "Total People: \(String(describing: self?.people?.count))"
    }
}

@IBAction func addHandler(_ sender: Any) {
    print(#function)
    let backgroundQueue = DispatchQueue(label: "com.app.queue",
                                        qos: .background,
                                        target: nil)



    backgroundQueue.async {
        print("Dispatched to background queue")
        let realm = try! Realm()
        try! realm.write {
            for i in 1..<50 {
                let name = String(format: "rajan-%d", i)
                //print(#function, name)
                realm.add(Person(name))
            }
        }

    }
}



回答3:


You could also use a ThreadSafe reference, a specific way to pass realm objects between threads:

let realm = try! Realm()
let person = Person(name: "Jane") // no primary key required 
try! realm.write {
    realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "com.example.myApp.bg").async {
    let realm = try! Realm()
    guard let person = realm.resolve(personRef) else {
    return // person was deleted
}
try! realm.write {
    person.name = "Jane Doe"
}

The steps provided by Realm Documentation:

  1. Initialize a ThreadSafeReference with the thread-confined object.
  2. Pass that ThreadSafeReference to a destination thread or queue.
  3. Resolve this reference on the target Realm by calling Realm.resolve(_:).
  4. Use the returned object as you normally would.


来源:https://stackoverflow.com/questions/41304476/realm-accessed-from-incorrect-thread-swift-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!