我正在尝试使用搜索栏搜索我使用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,我不知道如何实现它。 我是否必须将我的搜索请求放入我正在使用的操作或每种方法中?
有人可以给我一个示例代码,让我知道应该如何做到这一点? 提前谢谢......
答案 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是唯一能够提供线程响应性的方法,而且通常不会产生许多线程的混乱。
希望你能用它来开始:)