3.3 NSProgress
不经常见到Foundation会完整的添加一个新类。他是一个稳定的框架。主要是因为不经常用到核心的类。然而iOS7提供了一个完整的新类NSProgress。
本质上,NSProgress是用来通过Objective-C代码产生进度报告的,分离每一个独立模块的进度。例如,你可以在一些数据上执行几个不同的任务,然后每个任务可以管理他自己的进度然后报告给他的父任务。
3.3.1NSProgress结构
NSProgress最简单的使用方法是报告一些任务集合的进度。例如,你有10个任务执行,当每个任务完成的时候你可以报告进度。当有一个任务完成的时候进度增加%10。然后在NSProgress的实例上使用Key Value Observing(KVO),你能够了解到这个实例的进度。你可以使用这个通知来更新进度条或者显示一个指示文字。
NSProgress有更多的用途。Apple通过这个父子类的关系结构使他更加强大。NSProgress的结构更像是网状树。每一个NSProgress有一个父类和多个子类。每一个实例有一个执行的工作单元的总数,当前任务会处理完成的子任务数的更新来反馈当前状态。这么做的话,父类也会被通知进度。
为了减少NSProgress实例的传递,每个线程有自己的NSProgress实例然后子实例可以直接从这个实例创建。没有这个功能,每个想要报告进度的任务不得不通过参数的方式来通知。
3.3.2报告进度
NSProgress使用非常简单。以下面的方法开始:
+(NSProgress *)progressWithTotalUnitCount:(int64_t)unitCount;
这个方法创建了一个NSProgress实例作为当前实例的子类,以要执行的任务单元总数来初始化。例如,如果任务是循环一个数组,然后你可能用数组数来初始化NSProgress实例。例如:
NSArray*array = /* ... */;
NSProgress*progress =
[NSProgressprogressWithTotalUnitCount:array.count];
[arrayenumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) {
// Perform an expensive operation onobj
progress.completedUnitCount = idx;
}];
随着迭代的进行,上面的代码会更新NSProgress实例来反映当前进度。
3.3.3接收进度更新
你可以通过下面的属性在任何时候获取任务进度:
@property(readonly) double fractionCompleted;
返回值是0到1,显示了任务的整体进度。当没有子实例的话,fractionCompleted就是简单的完成任务数除以总得任务数。
Key Value Observing(KVO)是最好的方法来获取fractionCompleted值得变化。这么做非常简单。你只需要做的是添加一个NSProgress的fractionCompleted属性的观察者。像下面这样:
[_progressaddObserver:self
forKeyPath:@"fractionCompleted"
options:NSKeyValueObservingOptionNew
context:NULL];
然后覆盖KVO的这个方法来获取改变:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void *)context
{
if (object == _progress) {
// Handle new fractionCompleted value
return;
}
// Always call super, incase it uses KVOalso
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
在这个方法中你可以获取fractionCompleted的值的改变。例如你可能改变进度条或者提示文字。
当然,当你处理完的时候记得注销KVO是很重要的。
[_progressremoveObserver:self
forKeyPath:@"fractionCompleted"
context:NULL];
你必须总是要注销的,如果你没有注销,当被注册的Object释放的时候就会Crash。所以如果必要的话在dealloc中注销作为最后的保障。
不经常见到Foundation会完整的添加一个新类。他是一个稳定的框架。主要是因为不经常用到核心的类。然而iOS7提供了一个完整的新类NSProgress。
本质上,NSProgress是用来通过Objective-C代码产生进度报告的,分离每一个独立模块的进度。例如,你可以在一些数据上执行几个不同的任务,然后每个任务可以管理他自己的进度然后报告给他的父任务。
3.3.1NSProgress结构
NSProgress最简单的使用方法是报告一些任务集合的进度。例如,你有10个任务执行,当每个任务完成的时候你可以报告进度。当有一个任务完成的时候进度增加%10。然后在NSProgress的实例上使用Key Value Observing(KVO),你能够了解到这个实例的进度。你可以使用这个通知来更新进度条或者显示一个指示文字。
NSProgress有更多的用途。Apple通过这个父子类的关系结构使他更加强大。NSProgress的结构更像是网状树。每一个NSProgress有一个父类和多个子类。每一个实例有一个执行的工作单元的总数,当前任务会处理完成的子任务数的更新来反馈当前状态。这么做的话,父类也会被通知进度。
为了减少NSProgress实例的传递,每个线程有自己的NSProgress实例然后子实例可以直接从这个实例创建。没有这个功能,每个想要报告进度的任务不得不通过参数的方式来通知。
3.3.2报告进度
NSProgress使用非常简单。以下面的方法开始:
+(NSProgress *)progressWithTotalUnitCount:(int64_t)unitCount;
这个方法创建了一个NSProgress实例作为当前实例的子类,以要执行的任务单元总数来初始化。例如,如果任务是循环一个数组,然后你可能用数组数来初始化NSProgress实例。例如:
NSArray*array = /* ... */;
NSProgress*progress =
[NSProgressprogressWithTotalUnitCount:array.count];
[arrayenumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) {
// Perform an expensive operation onobj
progress.completedUnitCount = idx;
}];
随着迭代的进行,上面的代码会更新NSProgress实例来反映当前进度。
3.3.3接收进度更新
你可以通过下面的属性在任何时候获取任务进度:
@property(readonly) double fractionCompleted;
返回值是0到1,显示了任务的整体进度。当没有子实例的话,fractionCompleted就是简单的完成任务数除以总得任务数。
Key Value Observing(KVO)是最好的方法来获取fractionCompleted值得变化。这么做非常简单。你只需要做的是添加一个NSProgress的fractionCompleted属性的观察者。像下面这样:
[_progressaddObserver:self
forKeyPath:@"fractionCompleted"
options:NSKeyValueObservingOptionNew
context:NULL];
然后覆盖KVO的这个方法来获取改变:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void *)context
{
if (object == _progress) {
// Handle new fractionCompleted value
return;
}
// Always call super, incase it uses KVOalso
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
在这个方法中你可以获取fractionCompleted的值的改变。例如你可能改变进度条或者提示文字。
当然,当你处理完的时候记得注销KVO是很重要的。
[_progressremoveObserver:self
forKeyPath:@"fractionCompleted"
context:NULL];
你必须总是要注销的,如果你没有注销,当被注册的Object释放的时候就会Crash。所以如果必要的话在dealloc中注销作为最后的保障。