我有一个大任务,包含几个子任务。我想为这个大任务添加进度报告。
为此,我想使用
正如您所看到的,子任务使用背景上下文来运行一些与Core Data相关的代码,而背景上下文将主上下文作为其父上下文。
这会导致进度条的“fractionCompleted”属性出现一些奇怪的KVO现象。
这是打印输出:
正如您所看到的,打印从1.0、0.5和1.0开始,然后到了0.66?!从这里开始,它表现得很正常,并像我预期的那样变成了1.0。
为此,我想使用
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相关的代码,而背景上下文将主上下文作为其父上下文。
这会导致进度条的“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的进度。
有任何想法为什么会发生这种情况?以及我该如何修复它?
我添加了一个非常简单的项目simple project来演示这个问题(您可以删除setParentContext:调用,以查看它在没有此调用的情况下运行良好)。