複数のサブタスクで構成される 1 つの大きなタスクがあります。その大きなタスクの進捗レポートを追加したいと思います。クラスのドキュメントによると、この種のサブタスクの進行状況は、その子 - 親メカニズムを使用して実行できます
。NSProgress
簡単にするために、1 つのサブタスクで構成される大きなタスクがあるとします (もちろん、実際にはさらに多くのサブタスクがあります)。だからこれは私がやったことです:
#define kFractionCompletedKeyPath @"fractionCompleted"
- (void)runBigTask {
_progress = [NSProgress progressWithTotalUnitCount:100]; // 100 is arbitrary
[_progress addObserver:self
forKeyPath:kFractionCompletedKeyPath
options:NSKeyValueObservingOptionNew
context:NULL];
[_progress becomeCurrentWithPendingUnitCount:100];
[self subTask];
[_progress resignCurrent];
}
- (void)subTask {
NSManagedObjectContext *parentContext = self.managedObjectContext; // self is AppDelegate in this example
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:parentContext];
[bgContext performBlockAndWait:^{
NSInteger totalUnit = 1000;
NSInteger completedUnits = 0;
NSProgress *subProgress = [NSProgress progressWithTotalUnitCount:totalUnit];
for (int i=0; i < totalUnit; i++) {
// run some Core Data related code...
completedUnits++;
subProgress.completedUnitCount = completedUnits;
}
}];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:kFractionCompletedKeyPath]) {
if ([object isKindOfClass:[NSProgress class]]) {
NSProgress *progress = (NSProgress *)object;
NSLog(@"progress… %f", progress.fractionCompleted);
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
ご覧のとおり、サブタスクはバックグラウンド コンテキストを使用して Core Data 関連のコードを実行し、バックグラウンド コンテキストはメイン コンテキストを親コンテキストとして使用します。
これにより、進行状況の「fractionCompleted」プロパティの奇妙な KVO が発生します。
これはプリントです:
progress… 1.000000 // why???
progress… 0.500000 // why?????
progress… 1.000000 // why???????
progress… 0.666650 // why???????????
progress… 0.666990
progress… 0.667320
progress… 0.667660
progress… 0.667990
progress… 0.668320
...
progress… 1.000000
ご覧のとおり、印刷は 1.0、0.5、1.0 で始まり、0.66 に進みます ?!
ここからは正常に動作し、予想どおり 1.0 になります。
なぜこれが起こっているのかを理解しようとしましたが、バックグラウンド コンテキストから親コンテキストを削除すると、正常に動作することに気付きました! 0.0 から 1.0 に進みます。
なぜこれが起こっているのですか?どうすればそれを修正できますか?
この問題を示すために、非常に単純なプロジェクトを追加しました(setParentContext: 呼び出しを削除して、それがなくても正常に機能することを確認できます)。