ASIHttpRequest-创建和执行request

同步请求

同步请求会在当前线程中执行,使用error属性来检查结束状态(要下载大文件,则需要设定downloadDestinationPath来保存文件到本地):

1
2
3
4
5
6
7
8
9
10
- ( 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,后面会讲到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- ( 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 ];
}

 

使用block

block这个东西,太鸡肋了。。。当然特定时候还是需要的。

在平台支持情况下,ASIHTTPRequest1.8以上支持block。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- ( 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的。

 

使用队列

创建NSOperationQueue或者ASINetworkQueue队列,我们还可以设定最大并发连接数:maxConcurrentOperationCount 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- ( 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:方法

如果需要对队列里面的每个request进行区分,那么可以设定request的userInfo属性,它是个NSDictionary,或者更简单的方法是设定每个request的tag属性,这两个属性都不会被发送到服务器。

不要使用request的URL来区分每个request,因为URL可能会改变(例如重定向),如果需要使用request的URL,使用[request originalURL],这个将永远返回第一个url。

对于ASINetworkQueue

ASINetworkQueue是NSOperationQueue的子类,提供更高级的特性(ASINetworkQueue的代理函数):

  • requestDidStartSelector
    当一个request开始执行时,这个代理函数会被调用。
  • requestDidReceiveResponseHeadersSelector
    当队列中的request收到服务器返回的头信息时,这个代理函数会被调用。对于下载很大的文件,这个通常比整个request的完成要早。
  • requestDidFinishSelector
    当每个request完成时,这个代理函数会被调用。
  • requestDidFailSelector
    当每个request失败时,这个代理函数会被调用。
  • queueDidFinishSelector
    当队列完成(无论request失败还是成功)时,这个代理函数会被调用。

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来避免这个现象。

 

安全地控制delegate防止request完成之前代理被释放

request并不retain它们的代理,所以有可能你已经释放了代理,而之后request完成了,这将会引起崩溃。大多数情况下,如果你的代理即将被释放,你一定也希望取消所有request,因为你已经不再关心它们的返回情况了。如此做:

1
2
3
4
5
6
7
8
// 代理类的dealloc函数
- ( void )dealloc
{
    [request clearDelegatesAndCancel ];
    [request release ];
    ...
    [ super dealloc ];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值