2016-02-26 4 views
0

У меня есть функция sync, которая периодически запускается, чтобы синхронизировать все несинхронизированные модели Realm (я использую этот флаг sync внутри моего приложения, просто чтобы проверить, обработал ли я уже эту модель).Realm.io: Синхронизация или Async?

Я использовал 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."): 
} 

ответ

2

Прежде всего, если вам не нужно хранить свойство sync в базе данных постоянно, вы можете добавить его в свой ignoredProperties, то вам не нужно будет транзакции записи на всех ,

Если у вас есть все основания для его хранения, вы также можете использовать транзакцию записи как неявный механизм блокировки.

Мы рекомендуем в Realm предлагать группировать транзакции записи крупным партиям вместо небольших транзакций. Это потому, что нашему MVCC необходимо сохранить все версии, к которым по-прежнему обращается поток, который еще не обновлен.

Предварительно я интерпретирую, что метод синхронизации фактически выполняет некоторую работу, а не просто переключает флаг sync и что myFunc обновляет контроллеры представлений новыми данными. Если метод sync можно запускать несколько раз одновременно, его нужно вызывать асинхронно/запускать из другого потока, поскольку основная очередь не является параллельной. Пока myFunc должен запускаться в основном потоке, потому что вы можете только обновить свой интерфейс. Это исключает возможность совместного использования одного и того же экземпляра Realm между этими двумя методами, поскольку аксессоры не являются потокобезопасными. Если вы инициируете обновления для своего пользовательского интерфейса из экземпляра Realm другого потока внутри большой транзакции записи в пакетном режиме в методе синхронизации, то обновления модели пока не отображаются. Таким образом, вам также потребуется пакет обновлений 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]; 
    }); 
} 
+0

Небольшая вещь: '[realm.inWriteTransaction]' должно быть '[realm inWriteTransaction]'. –

+0

Спасибо, исправил. – marius