iphone - NSOperations 或 NSThread 用于突发不断相互取消的较小任务?

标签 iphone cocoa-touch nsthread

我想看看是否可以针对网络服务实现“键入时搜索”,并且经过充分优化,可以在 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/

相关文章:

iphone - 在 UITextView 中连续退格许多字符

iphone - CL位置距离 NaN

ios - 从 Swift 中的特定线程运行代码

objective-c - performSelector In Background 在关闭 View 时导致随机崩溃

iphone - TextField验证

iphone - 全屏 UIView 不会为其外观设置动画

objective-c - 在 objective-c 中声明属性和 @property 之间的区别

iphone - 我的 UIViewController 怎么知道是谁把它放到堆栈上的?

iphone - 如何停止nsthread

iphone - 设计一个使用 2 个 Restful Web 服务的应用程序