zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    Codeforces 845E Fire in the City 线段树
    Codeforces 542D Superhero's Job dp (看题解)
    Codeforces 797F Mice and Holes dp
    Codeforces 408D Parcels dp (看题解)
    Codeforces 464D World of Darkraft
    Codeforces 215E Periodical Numbers 容斥原理
    Codeforces 285E Positions in Permutations dp + 容斥原理
    Codeforces 875E Delivery Club dp
    Codeforces 888F Connecting Vertices 区间dp (看题解)
    Codeforces 946F Fibonacci String Subsequences dp (看题解)
  • 原文地址:https://www.cnblogs.com/zhwl/p/2591752.html
Copyright © 2011-2022 走看看