Mam jedno duże zadanie, które składa się z kilku podzadań. i chcę dodać raport postępu dla tego dużego zadania.
do tego chcę użyć NSProgress
, a zgodnie z dokumentacją klasy mogę wykonać tego rodzaju podzadania postępów za pomocą jego mechanizm podrzędny - rodzic.NSProgress dziwne zachowanie
Aby to uprościć, powiedzmy, że mam duże zadanie, które składa się z jednej podzadania (oczywiście w prawdziwym życiu byłoby więcej podzadań). Więc to jest to, co mam zrobić:
#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];
}
}
Jak widać, podzadanie wykorzystuje kontekst tła do uruchomienia niektórych danych Core kod związany, a kontekst tło wykorzystuje główny kontekst jako jego kontekstu macierzystego.
Powoduje to pojawienie się dziwnego KVO dla właściwości "fractionCompleted" postępu.
to jest druk:
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
Jak widać wydruk rozpoczyna się 1,0, 0,5 i 1,0, a potem to idzie do 0,66?!
stąd działa normalnie i przechodzi do wersji 1.0, jak się spodziewam.
Próbowałem zrozumieć, dlaczego tak się dzieje, i zauważyłem, że jeśli usunę kontekst nadrzędny z tła kontekstowego, działa dobrze! Dostaję postęp od 0,0 do 1,0.
Jakieś pomysły, dlaczego tak się dzieje? i jak mogę to naprawić?
dodałem bardzosimple project zademonstrować ten problem (można usunąć setParentContext: zadzwoń, aby zobaczyć, że to działa dobrze bez niego)
Najlepsza dokumentacja dla NSProgress znajduje się tutaj: https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/ – quellish