我对NSOperation有些新意。我有一个可能长时间运行的应用程序的现有应用程序。该任务通过Web服务下载数据。这项任务可能需要一些时间才能完成,特别是在连通性较慢的农村地区。我们需要更新此应用程序,以便用户可以取消下载,或者它可以自行超时。
目前我们正在使用GCD执行下载,但无法取消GCD操作。优选地,不会修改下载数据的类,而是将其视为任何长时间运行的操作。该对象的初始化程序获取Web服务数据,并在完成后返回。
我不确定是使用NSInvocationOperation还是使用NSOperation的子类。任务非常简单,只是为了取消操作。
MBProgressHUD用作活动指示器,并且具有将被使用的手势识别器,因此用户可以点击它以取消操作。此外,该操作应提供超时。操作完成后,将对UI进行更改。
目前的GCD代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^{
// long running operation
GaugeList *rg = [[GaugeList alloc] initWithStationInfo:[station id] forHistoryInHours:48 inThisFormat:nil];
dispatch_async(dispatch_get_main_queue(), ^{
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
GaugeViewController *vc = [sb instantiateViewControllerWithIdentifier:@"GaugeDetailViewController"];
[vc setRiverGauge:rg];
[self.navigationController pushViewController:vc animated:YES];
[hud removeFromSuperview];
});
我正在寻找一个快速的解决方案,但我见过的大多数例子都很冗长,可能需要进行大量的重构。任何人都可以指出一个提供解决方案的例子吗?谢谢! });
答案 0 :(得分:1)
NSInvocationOperation
不支持取消。它只是让您能够在操作队列上执行现有方法。如果要取消,则必须编写NSOperation
子类。取消支持确实需要你做一些工作,因为在-main
子类的NSOperation
方法(你把你的长期工作放在哪里),你需要不断检查isCancelled
属性确定何时从方法返回并结束操作(即,如果忽略isCancelled
标志并且-main
中的代码继续运行,则取消将不起作用)。
基本上,你想创建一个带有委托的NSOperation
子类,你可以在(在主队列上)调用一个方法来通知长时间运行的后台操作已经完成,然后让你长时间运行-main
中的代码,定期检查-isCancelled
,以确保您快速响应取消。
这样的事情:
@protocol MyOperationDelegate <NSObject>
@required
- (void)myOperationDidComplete:(MyOperation *)operation;
@end
@interface MyOperation : NSOperation
@property (nonatomic, assign) id<MyOperationDelegate> delegate
@end
@implementation MyOperation
- (void)main {
@autoreleasepool {
// Long running work
// Regularly check -isCancelled throughout the work, like this:
if ([self isCancelled]) {
// Cleanup
return;
}
// At the end of the work
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate myOperationDidComplete:self];
});
}
}
@end