写入后台 Realm 的数据不能立即用于主 Realm
Data written to a background Realm is not available immediately to main Realm
我有如下设置:
// Queues
private static let mainQueue = dispatch_get_main_queue()
private static let writeQueue = dispatch_queue_create("com.tablelist.Tablelist.queue.realm.write", DISPATCH_QUEUE_SERIAL)
// Realms
private static let defaultRealm: Realm = try! Realm()
private static func getDefaultRealm(block: (Realm) -> ()) {
Dispatch.async(mainQueue) {
block(defaultRealm)
}
}
private static func getWriteRealm(block: (Realm) -> ()) {
Dispatch.async(writeQueue) {
block(try! Realm())
}
}
最初我有一个 writeRealm
但由于 GCD 不保证队列中的块是哪个线程 运行,我被迫每次都创建一个新的 Realm
写函数。
然后我有一个 public func:
/**
Asynchronously write data to the realm
*/
public static func write(block: (Realm) -> ()) -> Promise<Realm> {
let promise = Promise<Realm>()
getWriteRealm { writeRealm in
do {
try writeRealm.write {
block(writeRealm)
}
getDefaultRealm { realm in
promise.resolve(realm)
}
}
catch {
Dispatch.main {
promise.resolve(error)
}
}
}
return promise
}
这允许调用者传入一个可以进行任何导入的块,然后在 promise 解析时在主线程上获取任何导入。问题是,有时导入的数据可用于主线程上的 Realm
,有时则不能。这里有更好的方法吗?
编辑:澄清一下,如果我在这两种情况下更改 write
函数以获取默认领域,我的所有测试都会通过。
解决方案:
private static func getDefaultRealm(block: (Realm) -> ()) {
Dispatch.async(mainQueue) {
defaultRealm.refresh() // refresh the realm to bring to most recent state
block(defaultRealm)
}
}
private static func getWriteRealm(block: (Realm) -> ()) {
Dispatch.async(writeQueue) {
let realm = try! Realm()
realm.refresh() // refresh the realm to bring to most recent state
block(realm)
}
}
解决方案 2:(进一步简化后)
private static func getDefaultRealm(block: (Realm) -> ()) {
let queue = dispatch_get_main_queue()
getRealm(queue, block: block)
}
private static func getWriteRealm(block: (Realm) -> ()) {
let queue = dispatch_queue_create("com.tablelist.Tablelist.queue.realm.write", nil)
getRealm(queue, block: block)
}
private static func getRealm(queue: dispatch_queue_t, block: (Realm) -> ()) {
Dispatch.async(queue) {
let realm = try! Realm()
realm.refresh()
block(realm)
}
}
tl;博士;调用 Realm.refresh()
将事务推进到最新状态。
Realm 的事务是独立的以提供自洽性。这允许随时在任何线程上执行事务,而无需您明确锁定或使用其他类型的资源协调。
Realm 中的读写事务均基于首次初始化时最近一次成功的写入提交,并保持该版本直到刷新。 Realm 会在每次 runloop 迭代开始时自动刷新,除非 Realm 的 autorefresh
属性 设置为 false
。如果一个线程没有runloop(后台线程通常是这种情况),那么必须手动调用Realm.refresh()
才能将事务推进到最近的状态。
写入事务提交时也会刷新领域 (Realm.commitWrite()
)。
我有如下设置:
// Queues
private static let mainQueue = dispatch_get_main_queue()
private static let writeQueue = dispatch_queue_create("com.tablelist.Tablelist.queue.realm.write", DISPATCH_QUEUE_SERIAL)
// Realms
private static let defaultRealm: Realm = try! Realm()
private static func getDefaultRealm(block: (Realm) -> ()) {
Dispatch.async(mainQueue) {
block(defaultRealm)
}
}
private static func getWriteRealm(block: (Realm) -> ()) {
Dispatch.async(writeQueue) {
block(try! Realm())
}
}
最初我有一个 writeRealm
但由于 GCD 不保证队列中的块是哪个线程 运行,我被迫每次都创建一个新的 Realm
写函数。
然后我有一个 public func:
/**
Asynchronously write data to the realm
*/
public static func write(block: (Realm) -> ()) -> Promise<Realm> {
let promise = Promise<Realm>()
getWriteRealm { writeRealm in
do {
try writeRealm.write {
block(writeRealm)
}
getDefaultRealm { realm in
promise.resolve(realm)
}
}
catch {
Dispatch.main {
promise.resolve(error)
}
}
}
return promise
}
这允许调用者传入一个可以进行任何导入的块,然后在 promise 解析时在主线程上获取任何导入。问题是,有时导入的数据可用于主线程上的 Realm
,有时则不能。这里有更好的方法吗?
编辑:澄清一下,如果我在这两种情况下更改 write
函数以获取默认领域,我的所有测试都会通过。
解决方案:
private static func getDefaultRealm(block: (Realm) -> ()) {
Dispatch.async(mainQueue) {
defaultRealm.refresh() // refresh the realm to bring to most recent state
block(defaultRealm)
}
}
private static func getWriteRealm(block: (Realm) -> ()) {
Dispatch.async(writeQueue) {
let realm = try! Realm()
realm.refresh() // refresh the realm to bring to most recent state
block(realm)
}
}
解决方案 2:(进一步简化后)
private static func getDefaultRealm(block: (Realm) -> ()) {
let queue = dispatch_get_main_queue()
getRealm(queue, block: block)
}
private static func getWriteRealm(block: (Realm) -> ()) {
let queue = dispatch_queue_create("com.tablelist.Tablelist.queue.realm.write", nil)
getRealm(queue, block: block)
}
private static func getRealm(queue: dispatch_queue_t, block: (Realm) -> ()) {
Dispatch.async(queue) {
let realm = try! Realm()
realm.refresh()
block(realm)
}
}
tl;博士;调用 Realm.refresh()
将事务推进到最新状态。
Realm 的事务是独立的以提供自洽性。这允许随时在任何线程上执行事务,而无需您明确锁定或使用其他类型的资源协调。
Realm 中的读写事务均基于首次初始化时最近一次成功的写入提交,并保持该版本直到刷新。 Realm 会在每次 runloop 迭代开始时自动刷新,除非 Realm 的 autorefresh
属性 设置为 false
。如果一个线程没有runloop(后台线程通常是这种情况),那么必须手动调用Realm.refresh()
才能将事务推进到最近的状态。
写入事务提交时也会刷新领域 (Realm.commitWrite()
)。