Realm写入阻止主线程

时间:2016-03-30 20:12:22

标签: swift realm

我在远程服务器上有一个json文件,我正在使用dataTaskWithURL从(36k记录)中获取数据。我返回了生成的JSON(SwiftyJSON)。下面是我的完成处理程序。

问题是,只要我开始遍历领域创建,我的所有其他回调都会停止执行,直到领域提交触发。我希望的结果是这个任务只是运行并在后台插入数据,允许用户在滚动时继续他们的快乐方式。

一旦realm.beginWrite()触发,就会发生阻塞。

RemoteAPI().getMetafile({JSONData, error -> Void in
            if (JSONData != nil) {
                do {
                    print("***** Loading realm")
                    let realm = try Realm()

                    realm.beginWrite()
                    for (_, subJSON) in JSONData {
                        realm.create(Meta.self, value: ["xxxxxx": subJSON["xxxxx"].int!, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxxx": subJSON["xxxxxx"].int!, "xxxxxx": subJSON["xxxxx"].stringValue, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxxx": subJSON["xxxxx"].stringValue], update: true)
                    }

                    try realm.commitWrite()

                    print("***** Finished loading realm")
                } catch _ {}
            } else {
                print("api data fetch failed")
                print(error)
            }
        })

虽然上述电话正在进行,但我还有另一个电话:

        RemoteAPI().getLatestActivityData({JSONData, error -> Void in
            if (JSONData != nil) {
                // do stuff

                dispatch_async(dispatch_get_main_queue(), {
                    NSNotificationCenter.defaultCenter().postNotificationName("refreshTableView", object: nil)
                })
            }
        })

这两个调用都来自app委托。然而,问题是第二次调用中的观察者在上面的第一次调用完成之后才会触发。

3 个答案:

答案 0 :(得分:0)

如果您不想阻止主线程,则应在后台执行事务。

...

do {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        let realm = try! Realm()

        realm.beginWrite()

        for (_, subJSON) in JSONData {
            realm.create(Meta.self, value: [...], update: true)
        }

        try realm.commitWrite()
    }
}
...

请参阅Realm docs有关线程的信息。

答案 1 :(得分:0)

该问题与线程阻塞无关。即使我异步运行请求,我想到的是,如果我有请求A 请求B 异步运行,他们都开始尝试执行Realm写入。它们基本上被视为串行请求,写入将排队,直到初始写入完成。

如文档中所述(不在线程部分中) - Realm写入将相互阻塞。他们注意到您可以使用线程来解决此问题,但即使使用 dispatch_async 方法,写入也会继续相互阻塞。

然而,我意识到初始请求只是加载要用于应用内搜索的数据而不是其他任何内容。系统的其余部分使用Realm存储用户特定数据。

我的解决方案

请求A 表示我填充的搜索元数据请求,因为我创建了一个新的域文件:

let config = Realm.Configuration(
                 path: utility.getDocumentsDirectory().stringByAppendingPathComponent("Meta.realm"),
                 readOnly: false)

let realm = try! Realm(configuration: config)

请求B 编写所有用户数据,然后触发我从默认域读取/写入的tableview刷新。

一旦我实现了这种使用方式的改变,就不再有阻塞,一切都正常工作,并且符合预期。

老实说,我不知道这是否是Swift / iOS的最佳实践(我不是Swift开发人员)但是它有效,而且性能完全可以接受。

答案 2 :(得分:0)

你可以试试这个:

for (_, subJSON) in JSONData {
    realm.beginWrite()
    realm.create(Meta.self, value: ["xxxxxx": subJSON["xxxxx"].int!, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxxx": subJSON["xxxxxx"].int!, "xxxxxx": subJSON["xxxxx"].stringValue, "xxxxx": subJSON["xxxxx"].stringValue, "xxxxxx": subJSON["xxxxx"].stringValue], update: true)
    try realm.commitWrite()
}

我不知道为什么,但它对我有用。