Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm.io - Realm accessed from incorrect thread swift

Tags:

ios

swift

realm

I want to download cities (name,id,lon,lat) from my .json file to Realm database.

I have created Realm object called City, but it crashes with the following error:

Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread'** 

So, I just want to get a Realm objects in my self.cities ([City]) array. Then to put it in the table view.

My refresh function:

func refresh(sender:AnyObject)
{

        var service = CityService()

        service.getCities {
            (response) in

            if(response.count > 0){
                if(response["cities"] != nil){
                    self.citiesStore.loadCities(response["cities"]! as NSArray,tableView: self.tableView)
                    self.tableView.reloadData()
                } else {
                    println("No response data")
                }
            }

}

Service:

class CityService {
var getCityUrl = "http://test:8888/cities.json";

func getCities(callback:(NSDictionary)->()) {
    get(getCityUrl,callback:callback)
}

func get(url:String, callback:(NSDictionary) -> ()){
    var nsURL = NSURL(string: url)

    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let task = NSURLSession.sharedSession().dataTaskWithURL(nsURL!) {
        (data,response,error) in
        var error: NSError?

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        if(error == nil){
            if(response != nil){
                var response = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
                callback(response)
            } else {
                callback(NSDictionary())
            }
        }

    }

    task.resume()
}

}

And loadCities function

func loadCities(citiesJson:NSArray,tableView: UITableView) {

    var realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL)

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_async(realmQueue) {
        println("start")

        var cc:[City] = []


        var realm = RLMRealm.defaultRealm()

        realm.beginWriteTransaction()

        for object in citiesJson {

            City.createOrUpdateInRealm(realm, withObject: object)

        }

        realm.commitWriteTransaction()

        let citiesFromRealm = City.allObjects()

        for object in citiesFromRealm {
            let cityObject = object as City

            //println(cityObject.name)  <-- here ok

            cc.append(cityObject)
        }

        println("point")

        dispatch_async(dispatch_get_main_queue()) {
            println("ok")
            self.cities.removeAll(keepCapacity: false)
            self.cities = cc

            println(self.cities[3].name) // <--- Here an error

            tableView.reloadData()
        }
    }


}
like image 940
mazy Avatar asked Feb 23 '15 20:02

mazy


1 Answers

The exception is telling you exactly what's going on -- an RLMRealm instances (and all the objects obtained from it) are only valid on a single thread. Every time you dispatch onto a separate queue, you'll need to create a new RLMRealm instance and re-fetch your RLMObjects before accessing any properties or starting a new write transaction.

like image 171
segiddins Avatar answered Oct 31 '22 16:10

segiddins