ASIHTTPRequest

1.创建并运行一个请求

1.1 创建一个同步请求

创建一个同步请求是使用ASIHTTPRequest的最简单的方式。发送消息startSynchronous会在同一个线程中执行这个请求,并且当请求结束的时候会返回控制权(成功或者其它的情况)。

通过error属性检查问题。

调用方法responseString从返回结果中获取字符串,不要使用这个方法获取二进制数据,使用方法responseData获得一个NSData对象。对于大的文件,设置你的请求的downloadDestinationPath属性用于下载文件。

      - (IBAction)grabURL:(id)sender

      {

               NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

               ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

               [request startSynchronous];

               NSError *error = [request error];

               if (!error) {

                       NSString *response = [request responseString];

               }

        }

注意:一般来说,你应该优先使用异步请求而不是同步请求。当你在主线程中使用ASIHTTPRequest的同步请求时,你的应用的用户界面会被锁定并且在整个网络请求期间不可用。

1.2 创建一个异步请求

做与上一个例子相同的事情,但是这个请求在后台运行。

       - (IBAction)grabURLInBackground:(id)sender

      {

              NSURL *url = [NSURL URLWithString:@"http://allseeing-i.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];

       }

我们设置了请求的delegate属性,所以当请求完成或失败时,我们能够接到通知。

这是创建异步请求的最简单的方式,它会在一个位于后台的全局的NSOperationQueue中运行。为了实现更多复杂的操作(例如跟踪多个请求的处理过程),你可能想创建自己的queue,这是下面将要讲到的。

1.3 使用blocks

从1.8版本起,我们可以在支持它们的平台上通过使用blocks完成上面例子的功能。

       - (IBAction)grabURLInBackground:(id)sender

      {

              NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

              __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

              [request setCompletionBlock:^{

                    // Use when fetching textdata

                    NSString *responseString = [request responseString];

                    // Use when fetching binarydata

                    NSData *responseData = [request responseData];

              }];

              [request setFailedBlock:^{

                    NSError *error = [request error];

              }];

              [request startAsynchronous];

       }

    注意当我们声明这个请求时标识符__block的使用,这是非常重要的!它告诉这个block不要retain这个请求,因为这个请求总是retain这个block,这样就避免了一个retain-cycle 。

1.4 使用队列

这个例子做相同的事情,但是这次我们为我们的请求创建一个NSOperationQueue。

使用你创建的NSOperationQueue(或者下面讲到的ASINetworkQueue),就可以对异步请求进行更多的控制。当使用一个queue的时候,只有一定数量的请求同时运行。如果你向一个队列中添加的请求多于属性maxConcurrentOperationCount指定的数量,多出的请求会等到其它的请求结束才能开始运行。

       - (IBAction)grabURLInTheBackground:(id)sender

       {

              if (![self queue]) {

                    [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];

              }

              NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

              ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

              [request setDelegate:self];

              [request setDidFinishSelector:@selector(requestDone:)];

              [request setDidFailSelector:@selector(requestWentWrong:)];

              [[self queue] addOperation:request]; //queue is anNSOperationQueue

       }

       - (void)requestDone:(ASIHTTPRequest *)request

       {

              NSString *response = [request responseString];

        }

        - (void)requestWentWrong:(ASIHTTPRequest *)request

       {

              NSError *error = [request error];

       }

       在上面的例子中,’queue’是我们控制器的一个retainedNSOperationQueue属性。

       我们设置自定义的selectors,它们会在请求成功或失败后被调用。如果你不设置这些,默认的(requestFinished:和requestFailed:)会向前面的例子中那样被使用。

 

1.5 在代理方法中处理多个请求的成功和失败状态

如果你需要处理多个请求的成功和失败的状态,你可以有几种选择:

1.           如果你的请求是相同的类型,但是你想区分它们,你可以用自定义的数据设置每个请求的字典类型的属性userInfo,这样你就可以在请求的成功或失败的代理方法中读取设置的值,通过这些值区分不同的请求。更简单的一种方式,你可以设置请求的tag属性。这两种属性是提供给你使用的,它们不会被发送到服务端。

2.           对于每个请求,如果你需要一个完全不同的方式处理成功或失败的返回结果,你可以针对每个请求设置不同的setDidFinishSelector和setDidFailSelector。

3.           对于更复杂的情况,或者说如果你想在后台解析返回结果,可以这堆每种类型的请求,创建ASIHttpRequest的一个最小子类,并且重载方法requestFinished:和failWithError:。

注意:最好避免在代理方法中通过请求的URL区分不同的请求,因为当重定向的时候URL属性会改变。如果你真的想使用请求的URL,可以使用[request originalURL],这样总会是第一次请求的url。

1.6 关于ASINetworkQueues

    ASINetworkQueue是类NSOperationQueue的子类,它提供了一些额外的功能。

它主要的目的是使你能够跟踪整个queue的上传和下载的过程。

另外,ASINetworkQueues提供了一些额外的代理方法:

l   requestDidStartSelector

    队列中的每个请求开始执行的时候调用这个方法。你可以使用它作为”设置你添加到queue的请求的代理方法并指定这个请求的didStartSelector”的替代方法。

l   requestDidReceiveResponseHeaderSeletor

当队列中的一个请求收到服务端回复的请求头时被调用。对于大数据量的下载,这个会在真正的下载完成之前被调用。你可以使用这个作为“设置你添加到queue中的请求的代理并且指定请求的didFailSelector”的一个替代方案。

l   requestDidFinishSelector

    当队列中一个请求成功时被调用。你可以使用这个作为“设置你添加到队列中请求的代理并指定一个didFinishSelector”的一个替代方案。

l    requestDidFailSelector

    当队列中一个请求失败时被调用。你可以使用这个作为“设置你添加到队列中请求的代理并指定一个didFailSelector”的一个替代方案。

l     queueDidFinishSelector

当整个队列完成时才被调用,不管单个的请求是成功还是失败。

要使用这些,可以设置队列的代理(而不是设置请求的代理)为实现这些selector的控制器。

       ASINetworkQueues的使用和NSOperationQueues有一点不同,就是添加到ASINetworkQueues的请求并不会马上开始执行。当使用一个ASINetworkQueue时,添加你想运行的操作,然后调用[queue go]。当你开启一个队列并打开“进度控制”标志时,它首先会为队列中的每个请求发送一个获取头部信息的请求,以获得要下载的数据的大小。一旦队列获得了要下载的大小,它能准确的显示整个下载过程,真正的下载也会开始。

注意:

       当你添加一个请求到一个已经开始的ASINetworkQueue中会发生什么?当你使用ASINetworkQueue跟踪一些请求的整个进展,当添加一个新的请求到队列,只有新的请求开始运行的时候,整个队列会进入后台运行。当队列开始运行的时候后,新添加的请求不会再请求头部信息,所以当你一次添加很多请求到一个已经开始运行的队列,整个进度不会立刻更新。

如果一个队列已经开始运行,你不需要再调用[queuego]。

 

    当ASINetworkQueue中的一个请求执行失败时,队列默认会取消所有的请求。你可以通过 [queue setShouldCancelAllRequestsOnFailure:NO]

取消这个属性。

 ASINetworkQueue只能运行ASIHTTPRequest操作,它们不能用于一般的操作。添加一个非ASIHTTPRequest的NSOperation会触发一个异常。

     注意:这个一个完整的演示基本的创建和使用ASINetworkQueue例子:http://gist.github.com/150447

1.7 取消一个异步请求

       调用[request cancel]取消一个异步请求(一个以[ [request startAsynchronous] ]开始的请求或者你创建的运行在队列中的请求)。注意你不能取消一个同步请求。

当你取消一个请求,这个请求会把这个当作一个错误,会调用请求的代理或者队列的代理的失败处理方法。如果你不希望这个行为,在取消一个请求之前设置这个请求的代理为nil或者使用方法clearDelegatesAndCancel取消请求。

           //Cancels an asynchronous request

           [requestcancel]

           //Cancels an asynchronous request, clearing all delegates and blocks first

            [requestclearDelegatesAndCancel];

使用一个ASINetworkQueue时,当你取消了队列中的一个请求,那么队列中所有的请求都会被取消除非你设置了队列的属性shouldCancelAllRequestsOnFailure为NO(YES是默认值)。

        // When a request inthis queue fails or is cancelled, other requests will continue to run

        [queuesetShouldCancelAllRequestsOnFailure:NO];

        // Cancel all requestsin a queue

        [queue cancelAllOperations];

1.8 当一个请求将要结束之前安全的处理即将被销毁的代理

请求不retain它们的代理,所以当请求正在执行的时候你的代理可能会被释放掉,清除请求的代理属性是至关重要的。在大多数情况下,如果你的代理将要被释放,你也不再关心这个请求的状态,所以你可能也想取消这个请求。

    在下面的例子中,我们的控制器有一个属性为retain的ASIHTTPRequest类型的实例变量。我们在方法delloc的实现中调用请求的clearDelegatesAndCancel方法,正好在在释放这个请求之前。

       // Ddealloc method for ourcontroller

       - (void)dealloc

       {

              [requestclearDelegatesAndCancel];

               [requestrelease];

               ...

              [superdealloc];

       }

2.发送数据

2.1 设置请求头

              ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

              [requestaddRequestHeader:@"Referer"value:@"http://allseeing-i.com/"];

2.2 使用ASIFormDataRequest发送一个POST请求

    可以使用ASIFormDataRequest发送与网页格式兼容的POST请求。以application/x-www-form-urlencoded格式POST数据或者以multipart/form-data格式POST二进制数据或文件。如果需要文件中的数据会从硬盘读取,所以可以提交大的文件,只要你的Web服务器支持处理它们。

              ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

              [request setPostValue:@"Ben"forKey:@"first_name"];

              [request setPostValue:@"Copsey"forKey:@"last_name"];

              [request setFile:@"/Users/ben/Desktop/ben.jpg"forKey:@"photo"];

       ASIFormDataRequest会自动检测通过方法setFile:forKey添加到POST的文件的mine类型,并且把这个添加到mime头中发送到服务端。如果你愿意,你可以使用更长的形式代替这种方式:

              ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

              // Upload a file on disk

              [request setFile:@"/Users/ben/Desktop/ben.jpg" withFileName:@"myphoto.jpg"andContentType:@"image/jpeg" forKey:@"photo"];

              // Upload an NSData instance

              [request setData:imageData withFileName:@"myphoto.jpg"andContentType:@"image/jpeg" forKey:@"photo"];

       你可以使用add接口针对一个参数发送多个值:

              ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

              [request addPostValue:@"Ben" forKey:@"names"];

              [request addPostValue:@"George"forKey:@"names"];

              [request addFile:@"/Users/ben/Desktop/ben.jpg"forKey:@"photos"];

              [requestaddData:imageData withFileName:@"george.jpg"andContentType:@"image/jpeg" forKey:@"photos"];

       查看ASIFormDataRequest.h获取向POST添加参数的全部的方法列表。

2.3 PUT请求和自定义POSTs

    如果你想通过PUT发送数据,或者想通过POST但是想自己创建POST包体,可以使用appendPostData:or appendPostDataFromFile:。

              ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

              [request appendPostData:[@"Thisis my data" dataUsingEncoding:NSUTF8StringEncoding]];

              // Default becomes POST when you useappendPostData: / appendPostDataFromFile: / setPostBody:

              [requestsetRequestMethod:@"PUT"];

       如果你想发送大量的数据但是不想使用ASIFormDataRequest,可以看下面将要介绍的“informationon streaming post bodies from disk ”。

3.下载数据

3.1 直接把回复内容下载到文件

如果你请求的资源非常的大,你可以直接下载到文件以节省内存。这样的话,ASIHTTPRequest不需要一下子在内存中维护所有的回复内容。

              ASIHTTPRequest*request = [ASIHTTPRequest requestWithURL:url];

              [requestsetDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"];

       当你使用属性downloadDestinationPath下载数据到一个文件时,在请求处理过程中数据会保存在一个临时文件中。当请求完成时,下面两个事情的其中一个会发生:

l   如果数据是gzip压缩的(查看gzip压缩数据),被压缩的文件会解压到downloadDestinationPath指定的路径下,临时文件会被删除。

l   如果数据不是压缩的,临时文件会被移动到downloadDestinationPath指定的路径下,并会覆盖同名的文件。

注意:如果回复的包体是空的,文件不会被创建。如果一个请求可能会返回一个空的包体,再你做任何尝试之前,请先检查下文件是否存在。

3.2 处理到来的回复数据

       如果你需要处理到来的包体数据(比如:当数据还在下载的时候使用“流解析“解析回复的数据),实现代理的request:didReceiveData:方法(查看ASIHTTPRequestDelegate.h)。注意当你这样做的时候,ASIHTTPRequest不会填充responseData,也不会把回复数据写入到downloadDestinationPath指定的路径,如果你需要你必须自己保存回复的数据。

3.3 读取HTTP状态码

对于大部分HTTP状态码,ASIHTTPRequest不会做任何特殊的事情(除了重定向和认证状态码,查看下面的内容获取更多信息),因此需要你查找问题并确认你是否操作得当。

              ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

              [request startSynchronous];

              int statusCode = [requestresponseStatusCode];

              NSString *statusMessage = [request responseStatusMessage];

3.4 读取回复的头部信息

              ASIHTTPRequest*request = [ASIHTTPRequest requestWithURL:url];

              [requeststartSynchronous];

              NSString*poweredBy = [[request responseHeaders]objectForKey:@"X-Powered-By"];

              NSString *contentType = [[requestresponseHeaders] objectForKey:@"Content-Type"];

3.5 处理文本编码

ASIHTTPRequest会尝试从头部的Content-Type字段读取接收到的数据的文本编码,如果它发现一个文本编码,它会设置字段responseEncoding为一个合适的 NSStringEncoding。如果它在头部字段没有发现一个文本编码,它会使用字段defaultResponseEncoding的默认值(这个字段默认值为NSISOLatin1StringEncoding)。

    当你调用[request responseString], ASIHTTPRequest会创建一个字符串,并尝试以responseEncoding指定的编码方式把接收到的数据转化到创建的字符串中。

3.6 处理重定向

ASIHTTPRequest会自动的重定向到一个新的URL当它遇到下面的一个HTTP状态码,假设一个本地的头已经发送:

l   301 Moved Permanently

l   302 Found

l   303 See Other

       当重定向发生时, responsedata的值(例如responseHeaders / responseCookies / responseData / responseString )会是从最后的地址接收到的值。

重定向的url的Cookies会存储到一个全局的cookie存储中,适当的时候会在一个重定向请求中表示服务器。

    你可以通过设置请求的属性shouldRedirect为NO关闭重定向。

注意:

       默认情况下,自动重定向只针对GET请求(没有消息体)。指定301和302重定向需要使用最初的方法符合多数浏览器的工作方式,不是HTTP协议特定的。

为了保存最初的方法(包括请求体)

针对301和302重定向,为了保存最初的方法(包括请求体),需要在请求开始执行之前,设置请求的属性shouldUseRFC2616RedirectBehaviour为YES。




ASIHTTPRequest对CFNetwork API进行了封装,并且使用起来非常简单,用Objective-C编写,可以很好的应用在Mac OS X系统和iOS平台的应用程序中。ASIHTTPRequest适用于基本的HTTP请求,和基于REST的服务之间的交互。

ASIHTTPRequest功能很强大,主要特色如下:

  • l 通过简单的接口,即可完成向服务端提交数据和从服务端获取数据的工作
  • l 下载的数据,可存储到内存中或直接存储到磁盘中
  • l 能上传本地文件到服务端
  • l 可以方便的访问和操作请求和返回的Http头信息
  • l 可以获取到上传或下载的进度信息,为应用程序提供更好的体验
  • l 支持上传或下载队列,并且可获取队列的进度信息
  • l 支持基本、摘要和NTLM身份认证,在同一会话中授权凭证会自动维持,并且可以存储在Keychain(Mac和iOS操作系统的密码管理系统)中
  • l 支持Cookie
  • l 当应用(iOS 4+)在后台运行时,请求可以继续运行
  • l 支持GZIP压缩数据
  • l 内置的ASIDownloadCache类,可以缓存请求返回的数据,这样即使没有网络也可以返回已经缓存的数据结果
  • l ASIWebPageRequest –可以下载完整的网页,包括包含的网页、样式表、脚本等资源文件,并显示在UIWebView /WebView中。任意大小的页面都可以无限期缓存,这样即使没有网络也可以离线浏览
  • l 支持客户端证书
  • l 支持通过代理发起Http请求
  • l 支持带宽限制。在iOS平台,可以根据当前网络情况来自动决定是否限制带宽,例如当使用WWAN(GPRS/Edge/3G)网络时限制,而当使用WIFI时不做任何限制
  • l 支持断点续传
  • l 支持同步和异步请求


1) 添加文件

往一个Xcode项目中添加第三方类库文件,有两种方式:

1. 第一种方式,在Finder中打开需要添加到文件或文件夹,在Xcode中打开要添加文件的项目,然后选中要添加的文件或文件夹,将它从Finder中拖到Xcode中,然后释放。在弹出的对话框中,如果文件已经拷贝到了项目文件目录中,则不需要选中“Copy items”的复选框;如果文件没有拷贝到项目文件目录,就需要选中“Copy items”的复选框,这样Xcode会自动把文件复制到项目文件目录下。如下图所示:
clip_image002
clip_image004

2. 第二种方式,在Xcode中,在要添加文件的分组下点右键,选中“Add Files to “My Project”…”菜单,在弹出的文件浏览对话框中选中要添加到文件或文件夹。如果要添加文件已经拷贝到了项目文件目录中,则不需要选中“Copy items”的复选框;如果文件没有拷贝到项目文件目录,就需要选中“Copy items”的复选框,这样Xcode会自动把文件复制到项目文件目录下。如下图所示:
clip_image006
clip_image008

根据上面的说明,添加ASIHTTPRequest相关文件到Xcode项目中,所需文件列表如下:

ASIHTTPRequestConfig.h

ASIHTTPRequestDelegate.h

ASIProgressDelegate.h

ASICacheDelegate.h

ASIHTTPRequest.h

ASIHTTPRequest.m

ASIDataCompressor.h

ASIDataCompressor.m

ASIDataDecompressor.h

ASIDataDecompressor.m

ASIFormDataRequest.h

ASIInputStream.h

ASIInputStream.m

ASIFormDataRequest.m

ASINetworkQueue.h

ASINetworkQueue.m

ASIDownloadCache.h

ASIDownloadCache.m

ASIAuthenticationDialog.h

ASIAuthenticationDialog.m

Reachability.h (在源码的 External/Reachability 目录下)

Reachability.m (在源码的 External/Reachability 目录下)

2) 链接相关类库

1. 选中项目

2. 选中目标

3. 跳转到“Build Phases”标签

4. 展开“Link Binary With Libraries”分组

5. 点击“+”添加类库

如下图所示:

clip_image010

6. 从列表中选择CFNetwork.framework,然后点击“Add”按钮。

clip_image012

7. 按照上一步相同的方法添加:SystemConfiguration.framework, MobileCoreServices.framework,CoreGraphics.framework和libz.1.2.3.dylib这几个类库。

8. 添加完后,可以将添加好的一起类库拖到Xcode项目的Frameworks目录下
clip_image014



在使用ASIHTTPRequest之前,请确认已经正确安装,然后在需要应用它的代码文件头部,加入:

#import “ASIHTTPRequest.h”

这样就可以在代码中使用ASIHTTPRequest相关的类。

发起一个同步请求

同步意为着线程阻塞,在主线程中使用此方法会使应用Hang住而不响应任何用户事件。所以,在应用程序设计时,大多被用在专门的子线程增加用户体验,或用异步请求代替(下面会讲到)。

- (IBAction)grabURL:(id)sender
{
   NSURL *url = [NSURL URLWithString:@ "http://allseeing-i.com" ];
   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
   [request startSynchronous];
   NSError *error = [request error];
   if (!error) {
     NSString *response = [request responseString];
   }
}

a, 用requestWithURL快捷方法获取ASIHTTPRequest的一个实例
b, startSynchronous 方法启动同步访问,
c, 由于是同步请求,没有基于事件的回调方法,所以从request的error属性获取错误信息。
d, responseString,为请求的返回NSString信息。

创建一个异步请求

异步请求的好处是不阻塞当前线程,但相对于同步请求略为复杂,至少要添加两个回调方法来获取异步事件。
下面异步请求代码完成上面同样的一件事情:

- (IBAction)grabURLInBackground:(id)sender
{
    NSURL *url = [NSURL URLWithString:@ "http://allseeing-i.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];
}

a,与上面不同的地方是指定了一个 "delegate",并用startAsynchronous来启动网络请求。
b,在这里实现了两个delegate的方法,当数据请求成功时会调用requestFinished,请求失败时(如网络问题或服务器内部错误)会调用requestFailed。

队列请求

提供了一个对异步请求更加精准丰富的控制。
如,可以设置在队列中,同步请求的连接数。往队列里添加的请求实例数大于maxConcurrentOperationCount时,请求实例将被置为等待,直到前面至少有一个请求完成并出列才被放到队列里执行。
也适用于当我们有多个请求需求按顺序执行的时候(可能是业务上的需要,也可能是软件上的调优),仅仅需要把maxConcurrentOperationCount设为“1”。

- (IBAction)grabURLInTheBackground:(id)sender
{
    if (![self queue]) {
       [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
    }
 
    NSURL *url = [NSURL URLWithString:@ "http://allseeing-i.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];
}

创建NSOperationQueue,这个Cocoa架构的执行任务(NSOperation)的任务队列。我们通过ASIHTTPRequest.h的源码可以看到,此类本身就是一个NSOperation的子类。也就是说它可以直接被放到"任务队列"中,并被执行。上面的代码队了队列的创建与添加操作外,其它代码与上一例一样。

请求队列上下文

a,可以设置一个上下文(userInfo)到request对象中,当请求响应完后可以通过访问request对象的userInfo获取里面的信息
b,为每一个请求实例设置不同的setDidFinishSelector / setDidFailSelector的回调方法
c,子类化ASIHTTPRequest,重写requestFinished: 与 failWithProblem:方法

ASINetworkQueues, 它的delegate提供更为丰富的功能

提供的更多的回调方法如下:
a,requestDidStartSelector,请求发起时会调此方法,你可以在此方法中跟据业务选择性的设置request对象的deleaget。
b,requestDidReceiveResponseHeadersSelector,当接受完响应的Header后设计此方法,这个对下载大数据的时候相当有用,你可以在方法里做更多业务上的处理。
c,requestDidFinishSelector,请求并响应成功完成时调用此方法
d,requestDidFailSelector,请求失败
e,queueDidFinishSelector,整个队列里的所有请求都结束时调用此方法。

它是NSOperationQueues的扩展,小而强大。但也与它的父类略有区别。如,仅添加到队列中其实并不能执行请求,只有调用[ queue g o]才会执行;一个正在运行中的队列,并不需要重复调用[ queue go ]。

默认情况下,队列中的一个请求如果失败,它会取消所有未完成的请求。可以设置[ queue setShouldCancelAllRequestsOnFailure:NO ]来修 正。

取消异步请求

首先,同步请求是不能取消的。
其次,不管是队列请求,还是简单的异步请求,全部调用[ request cancel ]来取消请求。

取消的请求默认都会按请求失败处理,并调用请求失败delegate。
如果不想调用delegate方法,则设置:[ request clearDelegatesAndCancel];

队列请求中需要注意的是,如果你取消了一个请求,队列会自动取消其它所有请求。
如果只想取消一个请求,可以设置队列:[ queue setShouldCancelAllRequestsOnFailure:NO ];
如果想明确取消所有请求:[ queue cancelAllOperations ];

安全的内存回收建议

request并没有retain你的delegate,所以在没有请求完的时候释放了此delegate,需要在dealloc方法里先取消所有请求,再释放请求实例,如:

- ( void )dealloc
{
    [request clearDelegatesAndCancel];
    [request release];
    ...
    [ super dealloc];
}
向服务器端上传数据

ASIFormDataRequest ,模拟 Form表单提交,其提交格式与 Header会自动识别。
没有文件:application/x-www-form-urlencoded
有文件:multipart/form-data

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@ "Ben" forKey:@ "first_name" ];
[request setPostValue:@ "Copsey" forKey:@ "last_name" ];
[request setFile:@ "/Users/ben/Desktop/ben.jpg" forKey:@ "photo" ];
[request addData:imageData withFileName:@ "george.jpg" andContentType:@ "image/jpeg" forKey:@ "photos" ];

如果要发送自定义数据:

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request appendPostData:[@ "This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
// Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
[request setRequestMethod:@ "PUT" ];
下载文件

通过设置request的setDownloadDestinationPath,可以设置下载文件用的下载目标目录。
首先,下载过程文件会保存在temporaryFileDownloadPath目录下。如果下载完成会做以下事情:
1,如果数据是压缩的,进行解压,并把文件放在downloadDestinationPath目录中,临时文件被删除
2,如果下载失败,临时文件被直接移到downloadDestinationPath目录,并替换同名文件。

如果你想获取下载中的所有数据,可以实现delegate中的request:didReceiveData:方法。但如果你实现了这个方法,request在下载完后,request并不把文件放在downloadDestinationPath中,需要手工处理。

获取响应信息

信息:status , header, responseEncoding

[request responseStatusCode];
[[request responseHeaders] objectForKey:@ "X-Powered-By" ];
  [request responseEncoding];
获取请求进度

有两个回调方法可以获取请求进度,
1,downloadProgressDelegate,可以获取下载进度
2,uploadProgressDelegate,可以获取上传进度

cookie的支持

如果Cookie存在的话,会把这些信息放在NSHTTPCookieStorage容器中共享,并供下次使用。
你可以用[ ASIHTTPRequest setSessionCookies:nil ] ; 清空所有Cookies。
当然,你也可以取消默认的Cookie策略,而使自定义的Cookie:

//Create a cookie
NSDictionary *properties = [[[NSMutableDictionary alloc] init] autorelease];
[properties setValue:[@ "Test Value" encodedCookieValue] forKey:NSHTTPCookieValue];
[properties setValue:@ "ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName];
[properties setValue:@ ".allseeing-i.com" forKey:NSHTTPCookieDomain];
[properties setValue:[NSDate dateWithTimeIntervalSinceNow: 60 * 60 ] forKey:NSHTTPCookieExpires];
[properties setValue:@ "/asi-http-request/tests" forKey:NSHTTPCookiePath];
NSHTTPCookie *cookie = [[[NSHTTPCookie alloc] initWithProperties:properties] autorelease];
 
//This url will return the value of the 'ASIHTTPRequestTestCookie' cookie
request = [ASIHTTPRequest requestWithURL:url];
[request setUseCookiePersistence:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request startSynchronous];
 
//Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie'
NSLog(@ "%@" ,[request responseString]);
大文件断点续传

0.94以后支持大文件的断点下载,只需要设置:
[ request setAllowResumeForFileDownloads:YES ];
[ request setDownloadDestinationPath:downloadPath ];
就可以了。

ASIHTTPRequest会自动保存访问过的URL信息,并备之后用。在以下几个场景非常有用:
1,当没有网络连接的时候。
2,已下载的数据再次请求时,仅当它与本地版本不样时才进行下载。

ASIDownloadCache 设置下载缓存

它对Get请求的响应数据进行缓存(被缓存的数据必需是成功的200请求):

[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];

当设置缓存策略后,所有的请求都被自动的缓存起来。
另外,如果仅仅希望某次请求使用缓存操作,也可以这样使用:

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
多种的缓存并存

仅仅需要创建不同的ASIDownloadCache,并设置缓存所使用的路径,并设置到需要使用的request实例中:

ASIDownloadCache *cache = [[[ASIDownloadCache alloc] init] autorelease];
[cache setStoragePath:@ "/Users/ben/Documents/Cached-Downloads" ];
[self setMyCache:cache];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[self myCache]];
缓存策略

缓存策略是我们控制缓存行为的主要方式,如:什么时候进行缓存,缓存数据的利用方式。
以下是策略可选列表(可组合使用):

ASIUseDefaultCachePolicy 这是一个默认的缓存策略“ASIAskServerIfModifiedWhenStaleCachePolicy”,这个很明白,见名知意(它不能与其它策略组合使用)
ASIDoNotReadFromCacheCachePolicy 所读数据不使用缓存
ASIDoNotWriteToCacheCachePolicy 不对缓存数据进行写操作
ASIAskServerIfModifiedWhenStaleCachePolicy 默认缓存行为,request会先判断是否存在缓存数据。a, 如果没有再进行网络请求。 b,如果存在缓存数据,并且数据没有过期,则使用缓存。c,如果存在缓存数据,但已经过期,request会先进行网络请求,判断服务器版本与本地版本是否一样,如果一样,则使用缓存。如果服务器有新版本,会进行网络请求,并更新本地缓存
ASIAskServerIfModifiedCachePolicy 与默认缓存大致一样,区别仅是每次请求都会 去服务器判断是否有更新
ASIOnlyLoadIfNotCachedCachePolicy 如果有缓存在本地,不管其过期与否,总会拿来使用
ASIDontLoadCachePolicy 仅当有缓存的时候才会被正确执行,如果没有缓存,request将被取消(没有错误信息)
ASIFallbackToCacheIfLoadFailsCachePolicy 这个选项经常被用来与其它选项组合使用。请求失败时,如果有缓存当网络则返回本地缓存信息(这个在处理异常时非常有用)
如果设置了“defaultCachePolicy”则所有的请求都会使用此缓存。
缓存存储方式

你可以设置缓存的数据需要保存多长时间,ASIHTTPRequest提供了两种策略:
a,ASICacheForSessionDurationCacheStoragePolicy,默认策略,基于session的缓存数据存储。当下次运行或[ASIHTTPRequest clearSession]时,缓存将失效。
b,ASICachePermanentlyCacheStoragePolicy,把缓存数据永久保存在本地,
如:

ASIHTTPRequest *request = [ ASIHTTPRequest requestWithURL:url ];
[ request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy ];

另外,也可以使用clearCachedResponsesForStoragePolicy来清空指定策略下的缓存数据。

缓存其它特性

设置是否按服务器在Header里指定的是否可被缓存或过期策略进行缓存:

[[ ASIDownloadCache sharedCache ] setShouldRespectCacheControlHeaders:NO ];

设置request缓存的有效时间:

[ request setSecondsToCache: 60 * 60 * 24 * 30 ]; // 缓存30天

可以判断数据是否从缓存读取:

[ request didUseCachedResponse ];

设置缓存所使用的路径:

[ request setDownloadDestinationPath:[[ ASIDownloadCache sharedCache ] pathToStoreCachedResponseDataForRequest:request ]];
实现自定义的缓存

只要简单的实现ASICacheDelegate接口就可以被用来使用。

使用代理请求

默认的情况下,ASIHTTPRequest会使用被设置的默认代理。但你也可以手动修改http代理:

// Configure a proxy server manually
NSURL *url = [ NSURL URLWithString:@ "http://allseeing-i.com/ignore" ];
ASIHTTPRequest *request = [ ASIHTTPRequest requestWithURL:url ];
[ request setProxyHost:@ "192.168.0.1" ];
[ request setProxyPort: 3128 ];
 
// Alternatively, you can use a manually-specified Proxy Auto Config file (PAC)
// (It's probably best if you use a local file)
[request setPACurl:[NSURL URLWithString:@ "file:///Users/ben/Desktop/test.pac" ]];
ASIHTTPRequest, 请求的其它特性

iOS4中,当应用后台运行时仍然请求数据:

[ request setShouldContinueWhenAppEntersBackground:YES ];

是否有网络请求:

[ ASIHTTPRequest isNetworkInUse ]

是否显示网络请求信息在status bar上:

[ ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO ];

设置请求超时时,设置重试的次数:

[ request setNumberOfTimesToRetryOnTimeout: 2 ];

KeepAlive的支持:

// Set the amount of time to hang on to a persistent connection before it should expire to 2 minutes
[ request setPersistentConnectionTimeoutSeconds: 120 ];
 
// Disable persistent connections entirely
[ request setShouldAttemptPersistentConnection:NO ];


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值