私は iOS 開発と Core Data テクノロジーを使い始めたところです。
私がやろうとしているのは、オブジェクトを 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;
}
このコードは、最初に何らかのアクションに対して今日すでに報酬が与えられているかどうかを確認し、そうでない場合は報酬を与えます。
このメソッドを同じパラメーターで 2 回呼び出します。
[rewardrewardForAction:APPLICATION_LAUNCH inManagedObjectContext: self.db.managedObjectContext]; [rewardrewardForAction:APPLICATION_LAUNCH inManagedObjectContext: self.db.managedObjectContext];
オブジェクトが 1 つだけ挿入されると予想されます。
しかし、実際には Core Data に 2 つのオブジェクトを挿入します。デバッガーでは、2 番目のフェッチ要求が既に存在する場合、オブジェクトを返さないことがわかります。
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;
}
}
奇妙なことに、シミュレーターでアプリを停止して再度実行すると、. 期待どおりにすべてのポイントを見ることができます。