Ich habe eine große Aufgabe, die aus mehreren Teilaufgaben bestehen. und ich möchte Fortschrittsberichte für diese große Aufgabe hinzufügen.
für das möchte ich NSProgress
verwenden, und entsprechend der Klassendokumentation kann ich diese Art von Subtask-Fortschritt tun, indem Sie seinen Kind-Eltern-Mechanismus verwenden.NSProgress seltsames Verhalten
Also, um es zu vereinfachen, nehmen wir an, ich habe große Aufgabe, die aus einer Teilaufgabe besteht (natürlich im wirklichen Leben gäbe es mehr Teilaufgaben). So ist es das, was ich getan habe:
#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];
}
}
Wie Sie sehen können, die Subtask verwendet Hintergrund Kontext einige Core Data bezogenen Code auszuführen, und der Hintergrund Kontext nutzt den Haupt Kontext als sein Elternkontext.
Dies verursacht einige seltsame KVO der Fortschritt "fractionCompleted" -Eigenschaft. diese
ist der Druck:
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
Wie Sie der Druck mit 1.0 beginnt sehen können, 0,5 und 1,0 und dann geht auf 0,66?!
von hier aus handelt es sich normal und geht auf 1.0 wie ich es erwarte.
Ich habe versucht zu verstehen, warum das passiert, und ich habe festgestellt, dass, wenn ich den übergeordneten Kontext aus dem Hintergrund Kontext entfernen, es funktioniert gut! Ich bekomme einen Fortschritt von 0.0 auf 1.0.
Irgendwelche Ideen, warum passiert das? und wie kann ich das beheben?
habe ich eine sehrsimple project dieses Problem zu demonstrieren (Sie können die setParentContext entfernen: rufen, dass es ohne es funktioniert gut zu sehen)
Die beste Dokumentation für NSProgress ist hier: https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/ – quellish