У меня есть одна большая задача, состоящая из нескольких подзадач. и я хочу добавить отчет о ходе выполнения этой большой задачи.
Для этого я хочу использовать NSProgress
, и в соответствии с документацией по классу я могу выполнить этот вид подзадачности, используя его дочерний механизм.NSProgress странное поведение
Итак, чтобы упростить его, скажем, у меня есть большая задача, состоящая из одной подзадачи (конечно, в реальной жизни было бы больше подзадач). Так вот что я сделал:
#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, и фоновый контекст использует основной контекст как его родительский контекст.
Это вызывает некоторые странные KVO свойства «fractionCompleted» прогресса.
это печать:
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.
Любые идеи, почему это происходит? и как я могу это исправить?
Я добавил оченьsimple project, чтобы продемонстрировать эту проблему (вы можете удалить setParentContext: позвонить, чтобы увидеть, что он хорошо работает и без него)
Лучшая документация для NSProgress находится здесь: https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/ – quellish