使用NSOperation搜索

时间:2010-12-14 16:52:57

标签: iphone nsoperation

我正在尝试使用搜索栏搜索我使用NSURLConnection收到的内容。 现在,如果我搜索某些内容,该字符串将作为带有异步请求的URL发送出去,这会为我提供数据。

NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
    [theConnection cancel];
    [theConnection release];

theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

解析数据并在成功时发布通知

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
     {       
         xmlParser = [[NSXMLParser alloc] data];
         [xmlParser setDelegate:xmlGeocoder];
         BOOL success = [xmlParser parse];

         if(success == YES){
             NSLog(@"No Errors");

             [[NSNotificationCenter defaultCenter] postNotificationName:@"getArray" object:self];

         }else{
             NSLog(@"Error Error Error!!!");
             [[NSNotificationCenter defaultCenter] postNotificationName:@"failToGetArray" object:self];
         }
}

我的searchresultsTableView被重新加载。

self.array1 = [array2 copy];
    [self.searchDisplayController.searchResultsTableView reloadData];

所有这些方法都依赖于彼此,因此当A仍然忙时,B无法执行。 我正在使用NSNotificationCenter告诉他们执行这些代码。

但我想尝试NSOperation,我不知道如何实现它。 我是否必须将我的搜索请求放入我正在使用的操作或每种方法中?

有人可以给我一个示例代码,让我知道应该如何做到这一点? 提前谢谢......

1 个答案:

答案 0 :(得分:2)

NSOperation非常有用。要使用它,您可以扩展NSOperation并覆盖“main”方法。 在主要方法中,您可以进行计算/ Web请求等。因此,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内部测试每个步骤是否按照你的意愿进行测试,并测试外面的东西是否取消了你的任务。):

- (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是唯一能够提供线程响应性的方法,而且通常不会产生许多线程的混乱。

希望你能用它来开始:)