私がやろうとしていること
以下のコードを使用して、バックエンド サーバー (parse.com) からアプリのコア データ ストアにデータ (過去の外国為替レート) をダウンロードしています。
アプリは、ローカルに保存されている最新の利用可能なデータをチェックし、サーバーから新しいデータのみをフェッチします。ローカルにまだデータが保存されていない場合は、サーバーからすべてのデータを取得します。
コードの設定方法は、100 個のオブジェクトのバッチでデータをフェッチし、コア データにオブジェクトを保存し、データが現在ローカルに保存されている新しい最新の日付を取得し (を使用してNSExpression
)、新しいデータがなくなるまで次のバッチをフェッチします。オブジェクトはサーバーに残されます ( objects.count = 0
)。
フェッチは遅いため、フェッチと Core Data の保存をバックグラウンド スレッドで実行することにしました (iOS 5 で提供される新しい Core Data マルチスレッド モデルを使用)。
バックエンド サーバーからのフェッチは正常に機能しますが、...
私の問題
NSExpression
これらのオブジェクトのみがディスク上に (物理的にはデータベースに) 保存されており、まだメモリ内にあり、すぐに保存されるオブジェクトは評価されないようです。したがって、フェッチはほとんどの場合、ディスク (メモリ) から「古い」値を取得します。
ただし、次のフェッチのコードを使用すると (noNSExpression
およびNSDictionary
as result 型を使用)、現在の正しい値が取得されます。
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:localEntityName];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];
request.sortDescriptors = @[sortDescriptor];
NSArray *results = [backgroundContext executeFetchRequest:request error:&error];
ForexHistory *forexHistoryItem = results.lastObject;
NSDate *lastLocalDate = forexHistoryItem.date;
NSLog(@"last local date results: %@",lastLocalDate);
NSExpression
と辞書を fetch resultType として使用する以下のコードの何が問題になっていますか?
私の質問
NSExpression
ローカルで利用可能な最新の日付を検索する が最新の日付を返すことを確認するにはどうすればよいですか?
コード
- (void)seedForexHistoryInManagedObjectContext:(NSManagedObjectContext*)context {
NSString* const localEntityName = @"ForexHistory";
NSString* const parseEntityName = localEntityName;
NSString* const parseDateIdentifier = @"date";
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"date"];
NSExpression *maxPeriodExpression = [NSExpression expressionForFunction:@"max:"
arguments:@[keyPathExpression]];
NSString *expressionName = @"maxDate";
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
expressionDescription.name = expressionName;
expressionDescription.expression = maxPeriodExpression;
expressionDescription.expressionResultType = NSDateAttributeType;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:localEntityName];
request.propertiesToFetch = @[expressionDescription];
request.resultType = NSDictionaryResultType;
NSArray *currencies = @[@"AUD",@"EUR",@"NZD",@"GBP",@"BRL",@"CAD",@"CNY"];
dispatch_queue_t downloadQueue;
downloadQueue = dispatch_queue_create("download", NULL); // create serial dispatch queue
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.parentContext = context;
dispatch_async(downloadQueue,^{
[moc performBlockAndWait:^{
NSArray *objects;
do {
NSError *error;
NSArray *dateResults = [moc executeFetchRequest:request error:&error];
NSAssert(dateResults.count == 1,@"Request error!");
NSDate *lastLocalDate = dateResults.lastObject[expressionName];
NSLog(@"last local date results: %@",lastLocalDate);
PFQuery *query = [PFQuery queryWithClassName:parseEntityName];
query.limit = 100;
[query orderByAscending:parseDateIdentifier];
if (lastLocalDate) [query whereKey:parseDateIdentifier greaterThan:lastLocalDate]; // else query all
objects = [query findObjects];
[objects enumerateObjectsUsingBlock:^(PFObject *obj, NSUInteger idx, BOOL *stop) {
ForexHistory *forexHistory = [NSEntityDescription insertNewObjectForEntityForName:localEntityName
inManagedObjectContext:moc];
forexHistory.date = NULL_TO_NIL(obj[@"date"]);
[currencies enumerateObjectsUsingBlock:^(NSString *currency, NSUInteger idx, BOOL *stop) {
[forexHistory setValue:NULL_TO_NIL(obj[currency]) forKey:currency.lowercaseString];
}];
}];
NSError *saveError = nil;
[moc save:&saveError];
if (!saveError) NSLog(@"%lu forex rates saved successfully.",(unsigned long)objects.count);
else NSLog(@"Error when downloading historic forex rates: %@",error.localizedDescription);
} while (objects.count > 0);
}];
}
ご協力ありがとうございました!