领域 sumOfProperty 不提供最新更新

Posted

技术标签:

【中文标题】领域 sumOfProperty 不提供最新更新【英文标题】:realm sumOfProperty does not give most recent update 【发布时间】:2015-12-11 05:15:06 【问题描述】:

Realm 0.96.3 大师。

我有一个创建两个Person 记录的测试。每个人都有一个NSNumber<RLMDouble> *walkDistance 属性。

人物模型

@interface Person : RLMObject
@property NSString  *id;
@property NSString  *name;
@property NSDate    *birthdate;
@property NSNumber<RLMDouble>  *walkDistance;
@property RLMArray<Dog *><Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person)

viewDidLoad

在一个表格视图中,我创建了一个RLMRealm self.database 和一个RLMResult self.persons。在viewDidLoad的主线程上:

self.bgq = dispatch_queue_create("com.salesram.bgqueu", NULL);
self.database = [self getEncryptedRealm];
self.persons = [[Person objectsInRealm:self.database withPredicate:nil]
__typeof__(self) __weak weakSelf = self;
self.token = [self.database addNotificationBlock:^(NSString * _Nonnull notification, RLMRealm * _Nonnull realm) 
    [weakSelf.tableView reloadData];
    [weakSelf calculateTotal];
];

getEncryptedRealm 是一个标准的 Realm 创建:

    NSData *key = [NSData dataWithBytes:c length:64];
    // Open the encrypted Realm file
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    config.encryptionKey = key;
    NSError *error;
    RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
    assert(realm != nil);

    return realm;

创建数据:

我有一个函数 createData 在后台线程中创建 2 个人。另一个函数清除后台线程中的所有对象,然后添加 2 个新人。他们都使用 GCD 相同的队列。所以它们按顺序运行。 [在同一个线程上并且(编辑:它们可以在不同的线程中运行)]

- (void)createData:(int)seq

dispatch_async(self.bgq, ^
    NSLog(@"start %i", seq);
    @autoreleasepool 
        RLMRealm *db = [self getEncryptedRealm];
        //[db refresh];
        [db beginWriteTransaction];
        for (int i = 0; i < 2; i++) 

            NSString *pid = [NSString stringWithFormat:@"%i", arc4random()%100];
            Person *person = [Person createOrUpdateInRealm:db withValue:@@"id": [NSString stringWithFormat:@"%@", pid]];
            person.name = [NSString stringWithFormat:@"Person Name # %@", pid];
            person.walkDistance = [NSNumber numberWithDouble:arc4random()%3+1];
            // omits some code of creating dogs...
        
        [db commitWriteTransaction];

        NSLog(@"end %i", seq);
    
);

清除数据库:

clearDB 将删除所有内容并在后台串行队列中重新创建所有内容。

- (IBAction)clearDB:(UIBarButtonItem *)sender

    dispatch_async(self.bgq, ^
        RLMRealm *db = [self getEncryptedRealm];
        [db beginWriteTransaction];
        [db deleteAllObjects];
        [db commitWriteTransaction];
    );
    [self createData:1];

计算总计

然后我在主线程上有一个函数来计算walkDistance的总和。它将由 commitWrite 上的 Realm 通知触发。

- (void)calculateTotal

    assert([NSThread isMainThread]);
    NSNumber *total = [self.persons sumOfProperty:@"walkDistance"];
    double miles = 0;
    for (Person *person in self.persons) 
        miles += [person.walkDistance doubleValue];
    
    NSString *title = [NSString stringWithFormat:@"%@ - %0.0f", total, miles];
    NSLog(@"%@", title);

问题

问题是当我用按钮触发clearDB 时,大多数时候我用sumOfProperty 方法得到的总距离为0。 for 循环添加始终有效。

从日志来看,似乎有两个通知被触发,calculateTotal 被调用了两次,一次在清除之后,一次在人口之后。但是sumOfProperty 似乎大部分时间都坚持第一个时间值,即 0。您可以看到日志的最后一行显示 0 - 6 而应该是 6 - 6

NSLog 输出

2015-12-10 21:25:38.686 dbrealmtest[18746:3258269] start 1
2015-12-10 21:25:38.686 dbrealmtest[18746:3258213] 1.358118751448067e-312 - 0
2015-12-10 21:25:38.692 dbrealmtest[18746:3258269] end 1
2015-12-10 21:25:38.693 dbrealmtest[18746:3258213] 0 - 6

这是一个已知问题吗?一个错误?还是我错过了什么?

谢谢

【问题讨论】:

我建议,如果你不检查你根本没有通过的错误指针。这将导致 Realm 的初始化程序引发异常,这会在日志中为您提供比 assert(realm != nil) 更有用的错误消息。 Yo 写道“它们都使用 GCD 相同的队列。所以它们在同一个线程上并按顺序运行。”。这不是真的。 GCD 不保证主队列旁边的执行线程。 @marius 我不明白你的第一条评论。你能再解释一下吗?对于第二条评论,是的。你说的对。它们不是由同一个线程执行的,而是按顺序执行的。这就是为什么我在每个 dispatch_async 的开头添加一个语句来获取一个新的 Realm。但它应该不会导致我看到的问题,对吧? @marius 创建领域中的断言始终通过。所以在每一个后台线程中,Realm都创建成功了。 你是对的。关于 GCD 的事实并没有导致问题,你在这里看到。我只是指出这一点以供进一步参考,以便您和其他人不要基于错误的假设。 :) 【参考方案1】:

记录更新:在further investigation 之后发现这是一个错误,自 0.97.1 版以来已修复。

【讨论】:

以上是关于领域 sumOfProperty 不提供最新更新的主要内容,如果未能解决你的问题,请参考以下文章

39页PDF《高效Transformers》最新综述!

百度ueditor编辑器 自动加P最新解决办法

腾讯云天天P图回应与“她拍”纠纷:授权提供人脸融合服务

将值、NULL 或不更新此列传递给 Oracle 表更新存储过程?

2020年将热门的8大IT职业领域

阿里云消息队列Kafka最新推出公网支持