使用ASIHttpRequest的setCompletionBlock、setFailedBlock时碰到一些诡异的内存泄漏和莫名其妙的行为(如:无法release对象)。
1. 声明ASIHttpRequest时一定要使用__block关键字
__block关键字告诉block不要retain request,这对于防止循环retain非常重要!!因为request总是会retain block
2. 谨慎处理block与对象的关系
当setCompletionBlock/setFailedBlock内部使用对象的instance var时,self会被retain(If you access an instance variable by reference, self is retained;)。所以在request结束前向对象发送release消息不会导致对象的释放(dealloc),亦即:该对象依然可进行所有操作,这将导致诸多你意想不到的结果。
3. 解决第2点的问题
3.1 仔细拿捏block与对象的关系 + 按值的方式访问instance var(If you access an instance variable by value, the variable is retained.)
3.2 不使用block,而使用ASIHttpRequestDelegate
4. 参考资料
4.1 http://allseeing-i.com/ASIHTTPRequest/How-to-use - Using blocks
4.2 Blocks Programming Topics - Object and Block Variables
接口部分:
//
// LYHASIRequestBlock.h
// ASIBlockTest
//
// Created by Charles Leo on 14-7-23.
// Copyright (c) 2014年 Charles Leo. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
typedef
void
(^RequestBlock) (
void
);
@interface
LYHASIRequestBlock
:
NSObject
<ASIHTTPRequestDelegate>
{
ASIHTTPRequest
* getRequest;
ASIFormDataRequest
* postRequest;
NSURL
* url;
RequestBlock
finishBlock;
RequestBlock
failBlock;
RequestBlock
startBlock;
NSString
* requestType;
}
//接收到的数据
@property
(strong,
nonatomic
)
NSData
* receiveData;
//请求完成的block
- (
void
)didFinishBlock:(RequestBlock)block;
//请求失败的block
- (
void
)didFailedBlock:(RequestBlock)block;
//请求开始的block
- (
void
)didStartBlock:(RequestBlock)block;
//取消请求
- (
void
)cancelRequst;
//get请求方法
- (
void
)getRequest:(
NSString
*)getUrl;
//post请求方法
- (
void
)postRequest:(
NSString
*)postUrl
andKeys
:(
NSArray
*)keyArray
andValues
:(
NSArray
*)valueArray;
@end
实现部分:
//
// LYHASIRequestBlock.m
// ASIBlockTest
//
// Created by Charles Leo on 14-7-23.
// Copyright (c) 2014年 Charles Leo. All rights reserved.
//
#import "LYHASIRequestBlock.h"
@implementation
LYHASIRequestBlock
- (
void
)getRequest:(
NSString
*)getUrl
{
requestType =
@"GET"
;
getRequest = [[
ASIHTTPRequest
alloc
]initWithURL:[
NSURL
URLWithString
:getUrl]];
getRequest
.delegate
=
self
;
getRequest
.timeOutSeconds
=
1
5
;
[getRequest
startAsynchronous
];
}
#pragma mark -GET请求的代理方法
//开始请求
- (
void
)requestStarted:(
ASIHTTPRequest
*)request
{
startBlock();
}
//请求完成
- (
void
)requestFinished:(
ASIHTTPRequest
*)request
{
self
.receiveData
= request
.responseData
;
finishBlock();
}
//请求失败
- (
void
)requestFailed:(
ASIHTTPRequest
*)request
{
failBlock();
}
//post请求
-(
void
)postRequest:(
NSString
*)postUrl
andKeys
:(
NSArray
*)keyArray
andValues
:(
NSArray
*)valueArray
{
postRequest = [[
ASIFormDataRequest
alloc
]initWithURL:[
NSURL
URLWithString
:postUrl]];
postRequest
.timeOutSeconds
=
1
5
;
postRequest
.delegate
=
self
;
for
(
int
i =
0
; i<keyArray
.count
; i++) {
[postRequest
setPostValue
:[valueArray
objectAtIndex
:i]
forKey
:[keyArray
objectAtIndex
:i]];
}
[postRequest
setDidFinishSelector
:
@selector
(didFinishPostRequest:)];
[postRequest
setDidStartSelector
:
@selector
(didStartPostRequest:)];
[postRequest
setDidFailSelector
:
@selector
(didFailPostRequest:)];
[postRequest
startAsynchronous
];
}
#pragma mark - POST请求的代理方法
//请求开始
- (
void
)didStartPostRequest:(
ASIFormDataRequest
*)request
{
startBlock();
}
//请求完成
- (
void
)didFinishPostRequest:(
ASIFormDataRequest
*)request
{
finishBlock();
}
//请求失败
- (
void
)didFailPostRequest:(
ASIFormDataRequest
*)request
{
failBlock();
}
//设置Blocks
//设置开始块
- (
void
)didStartBlock:(RequestBlock)block
{
[startBlock
release
];
startBlock = [block
copy
];
}
//设置完成块
-(
void
)didFinishBlock:(RequestBlock)block
{
[finishBlock
release
];
finishBlock = [block
copy
];
}
//设置失败块
-(
void
)didFailedBlock:(RequestBlock)block
{
[failBlock
release
];
failBlock = [block
copy
];
}
//取消请求
- (
void
)cancelRequst{
if
([requestType
isEqualToString
:
@"GET"
])
{
[getRequest
cancel
];
}
else
if
([requestType
isEqualToString
:
@"POST"
])
{
[postRequest
cancel
];
}
}
-(
void
)dealloc
{
[getRequest
release
];
[postRequest
release
];
[startBlock
release
];
[finishBlock
release
];
[failBlock
release
];
[
super
dealloc
];
}
@end
参考:http://www.cocoachina.com/bbs/read.php?tid=95100
http://code4app.com/snippets/one/%E7%94%A8Block%E5%B0%81%E8%A3%85ASIHttpRequest/5428f5b8933bf0bf118b51d8