Realm.io:同步还是异步?

时间:2016-02-26 02:49:54

标签: objective-c realm

我有一个定期运行的函数sync,用于同步所有未同步的Realm模型(我在我的应用程序内部使用此sync标志,只是为了检查我是否已处理模型或不是)。

我使用NSLock作为保护,因为sync可能同时运行多次。

我遇到的问题是,有时会多次处理相同的模型。 我想知道我的代码中是否存在任何问题,以及如何解决它(我认为可能是因为realm.io可能是异步的)。

@property (strong, nonatomic) NSLock *lock;

- (void)sync
{
    if (![self.lock tryLock]) return;

    RLMResults *models = [Model objectsWhere:@"sync = 0"];
    for (Model *model in models) {

        [realm beginWriteTransaction];
        model.sync = 1; // 1 step - Required to run the function.
        [realm commitWriteTransaction];

        [self myFunc]; // 2 step.

    [self.lock unlock];
}

- (void)myFunc
{
    NSLog(@"Updating view controller."):
}

1 个答案:

答案 0 :(得分:2)

首先,如果您不需要将资源sync永久保存在数据库中,您也可以将其添加到ignoredProperties,然后您就不需要了一个写交易。

如果你有充分的理由将它存储在那里,你也可以使用write事务作为隐式锁定机制。

我们建议Realm支持将写入事务分组到大批量而不是大量小事务。这是因为我们的MVCC需要保留所有仍然被线程访问的版本,但尚未更新。

事先我解释说sync方法实际上做了一些工作,而不仅仅是切换sync标志,而myFunc正在用新数据更新视图控制器。如果sync方法可以同时运行多次,则必须从另一个线程异步调用/运行它,因为主队列不是并发的。虽然myFunc必须在主线程上运行,因为您只能从那里更新UI。这排除了它在这两种方法之间共享相同的Realm实例,因为访问器不是线程安全的。如果从同步方法中的大批量写入事务中的另一个线程的Realm实例触发UI更新,则模型更新尚未可见。因此,您还需要批量处理UI更新。

- (void)sync {
    if (realm.inWriteTransaction) {
        return;
    }
    [realm beginWriteTransaction];

    RLMResults *models = [Model objectsWhere:@"sync = 0"];
    NSArray *modelIds = [models valueForKey:@"primaryKey"];
    for (Model *model in models) {
        model.sync = 1; // 1st step.
        // More expensive background work happens here?
    }
    [realm commitWriteTransaction];

    // Asynchronous batched 2nd step.
    dispatch_async(dispatch_get_main_queue(), ^{
        [self myFuncWithUpdatedModelIds:modelIds];
    });
}