同步请求 安全
同步请求会在当前线程中执行,使用error属性来检查结束状态(要下载大文件,则须要设定downloadDestinationPath来保存文件到本地): 服务器
- (IBAction)grabURL:(id)sender { NSURL *url = [NSURL URLWithString:@"http://www.dreamingwish.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request startSynchronous]; NSError *error = [request error]; if (!error) { NSString *response = [request responseString]; } }
同步请求会阻塞主线程的执行,这致使用户界面不响应用户操做,任何动画都会中止渲染。 并发
下面是最简单的异步请求方法,这个request会在全局的NSOperationQueue中执行,若要进行更复杂的操做,咱们须要本身建立NSOperationQueue或者ASINetworkQueue,后面会讲到。 异步
- (IBAction)grabURLInBackground:(id)sender { NSURL *url = [NSURL URLWithString:@"http://www.dreamingwish.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self]; [request startAsynchronous]; } - (void)requestFinished:(ASIHTTPRequest *)request { // Use when fetching text data NSString *responseString = [request responseString]; // Use when fetching binary data NSData *responseData = [request responseData]; } - (void)requestFailed:(ASIHTTPRequest *)request { NSError *error = [request error]; }
在平台支持状况下,ASIHTTPRequest1.8以上支持block。 函数
- (IBAction)grabURLInBackground:(id)sender { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^{ // Use when fetching text data NSString *responseString = [request responseString]; // Use when fetching binary data NSData *responseData = [request responseData]; }]; [request setFailedBlock:^{ NSError *error = [request error]; }]; [request startAsynchronous]; }
注意,声明request时要使用__block修饰符,这是为了告诉block不要retain request,以避免出现retain循环,由于request是会retain block的。 fetch
建立NSOperationQueue或者ASINetworkQueue队列,咱们还能够设定最大并发链接数:maxConcurrentOperationCount 动画
- (IBAction)grabURLInTheBackground:(id)sender { if (![self queue]) { [self setQueue:[[[NSOperationQueue alloc] init] autorelease]]; [self queue].maxConcurrentOperationCount = 4; } NSURL *url = [NSURL URLWithString:@"http://www.dreamingwish.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self]; [request setDidFinishSelector:@selector(requestDone:)]; [request setDidFailSelector:@selector(requestWentWrong:)]; [[self queue] addOperation:request]; //queue is an NSOperationQueue } - (void)requestDone:(ASIHTTPRequest *)request { NSString *response = [request responseString]; } - (void)requestWentWrong:(ASIHTTPRequest *)request { NSError *error = [request error]; }
若是不设定selector,那么系统会使用默认的requestFinished: 和 requestFailed:方法 url
若是须要对队列里面的每一个request进行区分,那么能够设定request的userInfo属性,它是个NSDictionary,或者更简单的方法是设定每一个request的tag属性,这两个属性都不会被发送到服务器。 线程
不要使用request的URL来区分每一个request,由于URL可能会改变(例如重定向),若是须要使用request的URL,使用[request originalURL],这个将永远返回第一个url。 代理
ASINetworkQueue是NSOperationQueue的子类,提供更高级的特性(ASINetworkQueue的代理函数):
ASINetworkQueues与NSOperationQueues稍有不一样,加入队列的request不会当即开始执行。若是队列打开了进度开关,那么队列开始时,会先对全部GET型request进行一次HEAD请求,得到总下载大小,而后真正的request才被执行。
向一个已经开始进行的ASINetworkQueue 加入request会怎样?
若是你使用ASINetworkQueue来跟踪若干request的进度,只有当新的request开始执行时,总进度才会进行自适应调整(向后移动)。ASINetworkQueue不会为队列开始后才加入的request进行HEAD请求,因此若是你一次向一个正在执行的队列加入不少request,那么总进度不会当即被更新。
若是队列已经开始了,不须要再次调用[queue go]。
当ASINetworkQueue中的一个request失败时,默认状况下,ASINetworkQueue会取消全部其余的request。要禁用这个特性,设置 [queue setShouldCancelAllRequestsOnFailure:NO]。
ASINetworkQueues只能够执行ASIHTTPRequest操做,二不能够用于通用操做。试图加入一个不是ASIHTTPRequest的NSOperation将会致使抛出错误。
取消一个异步请求(不管request是由[request startAsynchronous]开始的仍是从你建立的队列中开始的),使用[request cancel]便可。注意同步请求不能够被取消。
注意,若是你取消了一个request,那么这个request将会被视为请求失败,而且request的代理或者队列的代理的失败代理函数将被调用。若是你不想让代理函数被调用,那么将delegate设置为nil,或者使用clearDelegatesAndCancel方法来取消request。
clearDelegatesAndCancel 将会首先清除全部的代理和block。
当使用ASINetworkQueue时,若是取消了队列中的一个request,那么队列中其余全部request都会被取消,能够设置shouldCancelAllRequestsOnFailure的值为NO来避免这个现象。
request并不retain它们的代理,因此有可能你已经释放了代理,而以后request完成了,这将会引发崩溃。大多数状况下,若是你的代理即将被释放,你必定也但愿取消全部request,由于你已经再也不关心它们的返回状况了。如此作:
// 代理类的dealloc函数 - (void)dealloc { [request clearDelegatesAndCancel]; [request release]; ... [super dealloc]; }