好的,我花了最后 8 个小时阅读那里的每个示例。我开始意识到我必须做一些“概念验证”代码,看看是否会为“每个”击键构建一个新线程存在速度问题。
事实证明,使用 NSOperation 和 NSOperationQueue 是绰绰有余的,无论是在速度方面,尤其是在简单性和抽象方面。
在每次击键后调用:
- (void) searchFieldChanged:(UITextField*) textField {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSString *searchString = textField.text;
if ([searchString length] > 0) {
[self performSelector:@selector(doSearch:) withObject:textField.text afterDelay:0.8f];
}
}
这主要是为了阻止代码表单开始搜索小于 800 毫秒的击键。分开。(如果不是小型触摸键盘,我会低很多)。
如果允许超时,则该进行搜索了。
- (void) doSearch:(NSString*) searchString {
[queue cancelAllOperations];
ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
[queue addOperation:searchOperation];
[searchOperation release];
}
取消当前在队列中的所有操作。每次启动新搜索时都会调用它,它确保已经在进行的搜索操作以有序的方式关闭,它还确保只有一个线程处于“未取消”状态。
ISSearchOperation 的实现非常简单:
@implementation ISSearchOperation
- (void) dealloc {
[searchTerm release];
[JSONresult release];
[parsedResult release];
[super dealloc];
}
- (id) initWithSearchTerm:(NSString*) searchString {
if (self = [super init]) {
[self setSearchTerm:searchString];
}
return self;
}
- (void) main {
if ([self isCancelled]) return;
[self setJSONresult:/*do webservice call synchronously*/];
if ([self isCancelled]) return;
[self setParsedResult:/*parse JSON result*/];
if ([self isCancelled]) return;
[self performSelectorOnMainThread:@selector(searchDataReady:) withObject:self.parsedResult waitUntilDone:YES];
}
@end
有两个主要步骤,从 Web 服务下载数据和解析。每次我检查搜索是否被取消后,[NSOperationQueue cancelAllOperations]
如果它已经取消,然后我们返回并且在 dealloc 方法中很好地清理了对象。
我可能必须为 Web 服务和解析设置某种超时,以防止队列在KIA对象上阻塞。
但是现在这实际上是闪电般的快,在我的测试中,我正在搜索一个 16.000 个条目的字典,并让 Xcode NSLog 将其记录到屏幕上(很好地减慢速度),每 800 毫秒。我通过计时器发出一个新的搜索字符串,从而在它完成其 NSLog 结果到屏幕循环之前取消旧的。NSOperationQueue 可以毫无问题地处理这个问题,而且不会超过几毫秒。正在执行的两个线程。UI 完全不受上述在后台运行的任务的影响。