我想看看是否可以针对网络服务实现“键入时搜索”,并且经过充分优化,可以在 iPhone 上运行。
这个想法是用户开始输入一个单词; “Foo”,在每个新字母之后我都会等待 XXX 毫秒。看看他们是否输入了另一个字母,如果没有,我会使用该单词作为参数来调用 Web 服务。
我想将 Web 服务调用和随后的结果解析移至不同的线程。
我编写了一个简单的SearchWebService类,它只有一个公共(public)方法:
- (void) searchFor:(NSString*) str;
此方法测试搜索是否已经在进行中(用户的输入有 XXX 毫秒的延迟),然后停止该搜索并开始新的搜索。当结果准备好时,调用委托(delegate)方法:
- (NSArray*) resultsReady;
我不知道如何让这个功能“线程化”。 如果我每次用户有 XXX 毫秒时不断生成新线程。打字延迟我最终陷入了许多线程的糟糕境地,特别是因为我不需要任何其他搜索,但需要最后一个搜索。 我尝试通过以下方式始终在后台运行一个线程,而不是连续生成线程:
- (void) keepRunning {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SearchWebService *searchObj = [[SearchWebService alloc] init];
[[NSRunLoop currentRunLoop] run]; //keeps it alive
[searchObj release];
[pool release];
}
但是我不知道如何访问“searchObj”对象中的“searchFor”方法,因此上面的代码可以工作并继续运行。我只是无法向 searchObj
发送消息或检索 resultReady
对象?
希望有人能指出我正确的方向,线程让我悲伤:) 谢谢。
最佳答案
好吧,我花了过去 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];
}
取消队列中当前的所有操作。每次新搜索时都会调用此方法 启动后,它确保已经在进行中的搜索操作以有序的方式关闭,它还确保只有 1 个线程处于“未取消”状态。
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
有两个主要步骤,从网络服务下载数据和解析。
每次之后,我都会检查搜索是否已被 [NSOperationQueue cancelAllOperations]
取消(如果有),然后我们返回,并且在 dealloc 方法中很好地清理了该对象。
我可能必须为 Web 服务和解析设置某种超时,以防止队列因 KIA 对象而阻塞。
但现在这实际上快如闪电,在我的测试中,我正在搜索 16.000 个条目的字典,并让 Xcode NSLog 将其记录到屏幕上(很好地减慢了速度),每次 800 毫秒。我通过计时器发出一个新的搜索字符串,从而在旧的搜索字符串完成 NSLog 结果到屏幕循环之前取消它。 NSOperationQueue 处理这个问题没有任何故障,而且不会超过几毫秒。正在执行的两个线程。 UI完全不受后台运行的上述任务的影响。
关于iphone - NSOperations 或 NSThread 用于突发不断相互取消的较小任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2840406/