领域 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 不提供最新更新的主要内容,如果未能解决你的问题,请参考以下文章