NSOperation 非常有用。要使用它,您可以扩展 NSOperation 并覆盖“main”方法。在主要方法中,您进行计算/网络请求等。因此 NSOperation 最适合您可以包装成几个简单步骤的任务,在每个步骤之后您测试一切是否正常,然后继续下一步或取消操作。完成此操作后,您可以简单地实例化您的自定义 NSOperation 并将其交给 NSOperationQueue 对象,它会处理线程、启动、停止清理等。
在下面的示例中,我编写了一个协议来处理任务的完成,我建议您采用这种方法而不是使用通知 - 除非您有多个需要立即通知的对象。
创建一个扩展 NSOperation 类的新类:
//This object takes a "searchTerm" and waits to be "started".
#import <Foundation/Foundation.h>
@protocol ISSearchOperationDelegate
- (void) searchDataReady:(NSArray*) searchResult;
@end
@interface ISSearchOperation : NSOperation {
id <ISSearchOperationDelegate> delegate;
NSString *searchTerm;
}
@property(nonatomic, retain) NSString *searchTerm;
@property(nonatomic, assign) id delegate;
- (id) initWithSearchTerm:(NSString*) searchString;
@end
当扩展 NSOperation 的对象被添加到 NSOperationQueue 时,队列对象会尝试调用 NSOperation 上的“main”方法,因此您必须将任务包装在此方法中。(请注意,在每个完成的子任务之后,我测试它是否顺利,如果不顺利,则“返回”。NSOperation 类有一个名为isCancelled的属性,此属性可以由 NSOperationQueue 设置,因此您还必须测试是否已在期间设置你完成了 main。所以回顾一下,你从 main 内部测试每个步骤是否按照你的意愿进行,并且你测试外部的某些东西是否取消了你的任务。):
- (id) initWithSearchTerm:(NSString*) searchString {
if (self = [super init]) {
[self setSearchTerm:searchString];
}
return self;
}
- (void) main {
[self performSelector:@selector(timeOut) withObject:nil afterDelay:4.0];
if ([self isCancelled]) return;
NSData *resultData = [self searchWebServiceForString:self.searchTerm];
if (resultData == nil) return;
if ([self isCancelled]) return;
NSArray *result = [self parseJSONResult:resultData];
if ([self isCancelled]) return;
if (result == nil) return;
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[delegate performSelectorOnMainThread:@selector(searchDataReady:) withObject:result waitUntilDone:YES];
}
//我没有复制我在main期间调用的所有方法的实现,但我希望你明白它们只是“任务”,每个必须成功完成才能计算下一个子任务。所以首先我在那里进行超时测试,然后我从 Web 服务中获取我的数据,然后我解析它。
好的,要让这一切顺利进行,您需要排队。
因此,在您想成为此操作的代表的班级中,您可以执行以下操作:
在某处设置队列:
NSOperationQueue *q = [[NSOperationQueue alloc] init];
[self setQueue:q];
[q release];
- (void) doSearch:(NSString*) searchString {
[queue cancelAllOperations];
ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
[searchOperation setDelegate:self];
[queue addOperation:searchOperation]; //this makes the NSOperationQueue call the main method in the NSOperation
[searchOperation release];
}
//the delegate method called from inside the NSOperation
- (void) searchDataReady:(NSArray*) results {
//Data is here!
}
NSOperations 的一些优点是,从调用者的角度来看,我们只需创建一个对象,设置一个委托,等待回复。但是在幕后运行了一系列可以随时取消的线程任务,并且以一种可以在线程失败时进行处理的方式运行。
正如您在 doSearch 方法中看到的那样,它从取消任何先前的操作开始,我在一个应用程序中执行此操作,每次用户在一个单词中输入一个字母时,我都会搜索一个 Web 服务。这意味着如果用户搜索“hello world”——我会搜索“h”,然后是“he”,然后是“hel”,然后是 hell”,然后是“hello”等等。我想停下来清理一下用户键入“e”后立即执行“h”任务,因为它已经过时了。我发现 NSOperation 是提供线程响应能力的唯一方法,并且没有通常在顶部产生许多线程所带来的混乱彼此的。
希望你可以用它开始:)