我刚刚开始玩 iOS 开发和 Core Data 技术。
我想要做的是将对象插入核心数据,然后在同一上下文中运行获取请求以查找新插入的对象。
这是我用来插入对象的代码:
+(Reward*) rewardForAction: (Actions) action
inManagedObjectContext: (NSManagedObjectContext *) context {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Reward"];
NSPredicate *actionPredicate =
[NSPredicate predicateWithFormat:@"action = %@",
[NSString stringWithFormat:@"%i", action]];
NSPredicate *todayPredicate =
[NSPredicate predicateWithFormat:@"when > %@",
[NSDate today]];
NSLog(@"Today's midnight :%@", [NSDate today]);
request.predicate =
[NSCompoundPredicate andPredicateWithSubpredicates:
[NSArray arrayWithObjects: actionPredicate, todayPredicate, nil]];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest: request error: &error];
Reward *reward = nil;
if(!matches) {
NSLog(@"ERROR: failed to retrieve rewards");
} else if(matches.count > 0) {
NSLog(@"WRONG: reward already exists");
} else {
reward = [NSEntityDescription insertNewObjectForEntityForName:@"Reward"
inManagedObjectContext:context];
reward.action = [NSNumber numberWithInt:action];
reward.when = [NSDate date];
reward.pointsEarned = [Reward getPointsForAction:action];
}
[Stats track: context];
[context save:nil];
return reward;
}
此代码首先检查今天是否已经为某些操作提供了奖励,如果没有,则提供奖励。
用相同的参数调用这个方法两次,像这样
[Reward rewardForAction:APPLICATION_LAUNCH inManagedObjectContext: self.db.managedObjectContext]; [Reward rewardForAction:APPLICATION_LAUNCH inManagedObjectContext: self.db.managedObjectContext];
预计只会插入一个对象。
但是,实际上它在核心数据中插入了两个对象。在调试器中,我看到第二个获取请求在已经存在对象时不返回任何对象。
看起来 NSFetchRequest 没有看到数据存储中的变化,并且对旧数据进行操作。我错过了什么吗?
编辑: 我还为 NSManagedObjectContextObjectsDidChangeNotification 设置了观察者,当它被调用时,我正在计算点的总和以将其反映在 UI 上。不幸的是 sum 也不包含来自插入对象的点。这是我计算总和的代码:
+(NSInteger) getPoints: (NSManagedObjectContext *) context {
Stats * stats= [Stats get: context];
NSArray *args = [NSArray arrayWithObject:
[NSExpression expressionForKeyPath:@"pointsEarned"]];
NSExpression *ex = [NSExpression expressionForFunction:@"sum:"
arguments:args];
NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
[ed setName:@"result"];
[ed setExpression:ex];
[ed setExpressionResultType:NSInteger32AttributeType];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setPropertiesToFetch:[NSArray arrayWithObject:ed]];
[request setResultType:NSDictionaryResultType];
/*if([stats intervalStartDate]) {
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"when >= %@", [stats intervalStartDate]];
[request setPredicate:predicate];
}*/
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Reward"
inManagedObjectContext:context];
[request setEntity:entity];
NSArray *results = [context executeFetchRequest:request error:nil];
if(results && results.count > 0) {
NSDictionary *resultsDictionary = [results objectAtIndex:0];
NSNumber *resultValue = [resultsDictionary objectForKey:@"result"];
return [resultValue intValue];
} else {
return 0;
}
}
奇怪的是,当我在模拟器上停止应用程序并再次运行它时。我可以按预期看到所有点。