0

我正在尝试制作一个搜索栏来搜索我使用 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,但我不知道如何实现它。我是否必须将我的搜索请求放入一个操作或我正在使用的每个方法中?

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

4

1 回答 1

2

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 是提供线程响应能力的唯一方法,并且没有通常在顶部产生许多线程所带来的混乱彼此的。

希望你可以用它开始:)

于 2010-12-14T21:31:57.300 回答