ASIHTTPRequest足够了吗?
大家都知道ASIHTTPRequest系列的类很好用,功能很强大。但也像NSURLConnection一样,一个网络请求就需要实例化一个对象,而且无法避免重复请求的问题。
我个人不习惯用ASIHTTPRequest,因为它功能太强大了,函数太多了,而我们平时的项目仅仅是处理基于HTTP协议的网络交互,用ASIHTTPRequest未免太“奢侈”了。更重要的是,它并无法避免网络的重复请求的问题,而且无法控制网络请求数量,所以仅仅使用ASIHTTPRequest还不够。
事实上,用NSURLConnection足够了。下面是我写的封装
HTTPConnection.h
1. <span style="font-size:16px;">//
2. // HTTPConnection.h
3. //
4. //
5. // Created by Jianhong Yang on 12-1-3.
6. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11.
12. #define MAXNUMBER_HTTPCONNECTION 30
13.
14. @protocol HTTPConnectionDelegate;
15.
16. @interface HTTPConnection : NSObject {
17. @private
18. //
19. int _numberOfHTTPConnection;
20. NSMutableArray *_marrayTaskDic;
21.
22. id <HTTPConnectionDelegate> _delegate;
23. }
24.
25. @property (nonatomic, assign) id <HTTPConnectionDelegate> delegate;
26.
27. // 根据URL获取Web数据
28. // dicParam
29. // type:int,请求类型
30. - (BOOL)requestWebDataWithURL:(NSString *)strURL andParam:(NSDictionary *)dicParam;
31.
32. // 根据URLRequest获取Web数据
33. // dicParam
34. // type:int,请求类型
35. - (BOOL)requestWebDataWithRequest:(NSURLRequest *)request andParam:(NSDictionary *)dicParam;
36.
37. //取消网络请求
38. - (BOOL)cancelRequest:(NSDictionary *)dicParam;
39.
40. //清空网络请求
41. - (void)clearRequest;
42.
43. @end
44.
45.
46. @protocol HTTPConnectionDelegate <NSObject>
47.
48. @optional
49.
50. // 网络数据下载失败
51. - (void)httpConnect:(HTTPConnection *)httpConnect error:(NSError *)error with:(NSDictionary *)dicParam;
52.
53. // 服务器返回的HTTP信息头
54. - (void)httpConnect:(HTTPConnection *)httpConnect receiveResponseWithStatusCode:(NSInteger)statusCode
55. andAllHeaderFields:(NSDictionary *)dicAllHeaderFields with:(NSDictionary *)dicParam;
56.
57. // 服务器返回的部分数据
58. - (void)httpConnect:(HTTPConnection *)httpConnect receiveData:(NSData *)data with:(NSDictionary *)dicParam;
59.
60. // 网络数据下载完成
61. - (void)httpConnect:(HTTPConnection *)httpConnect finish:(NSData *)data with:(NSDictionary *)dicParam;
62.
63. @end
64.
65.
66. #ifdef DEBUG
67.
68. #define HTTPLOG(fmt,...) NSLog((@"HTTP->%s(%d):"fmt),__PRETTY_FUNCTION__,__LINE__,##__VA_ARGS__)
69.
70. #else
71.
72. #define HTTPLOG(fmt,...) NSLog(fmt,##__VA_ARGS__)
73.
74. #endif</span>
HTTPConnection.m
[plain] view plaincopy
1. //
2. // HTTPConnection.m
3. //
4. //
5. // Created by Jianhong Yang on 12-1-3.
6. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7. //
8.
9. #import "HTTPConnection.h"
10.
11.
12. @interface HTTPConnection (Private)
13. - (void)startHTTPConnection;
14. @end
15.
16.
17. @implementation HTTPConnection
18.
19. @synthesize delegate = _delegate;
20.
21. - (id)init
22. {
23. self = [super init];
24. if (self) {
25. // Custom initialization.
26. _numberOfHTTPConnection = 0;
27. _marrayTaskDic = [[NSMutableArray alloc] initWithCapacity:5];
28. }
29. return self;
30. }
31.
32. - (void)dealloc
33. {
34. //清空任务
35. [self clearRequest];
36. //
37. [_marrayTaskDic release];
38.
39. [super dealloc];
40. }
41.
42.
43. #pragma mark -
44. #pragma mark Public
45.
46. // 根据URL获取Web数据
47. // dicParam
48. // type:int,请求类型
49. - (BOOL)requestWebDataWithURL:(NSString *)strURL andParam:(NSDictionary *)dicParam
50. {
51. if (nil == dicParam) {
52. return NO;
53. }
54.
55. NSURL *url = [NSURL URLWithString:strURL];
56. NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
57. BOOL success = [self requestWebDataWithRequest:request andParam:dicParam];
58. [request release];
59. return success;
60. }
61.
62. // 根据URLRequest获取Web数据
63. // dicParam
64. // type:int,请求类型
65. - (BOOL)requestWebDataWithRequest:(NSURLRequest *)request andParam:(NSDictionary *)dicParam
66. {
67. if (nil == dicParam) {
68. return NO;
69. }
70. //请求类型必须存在
71. if (nil == [dicParam objectForKey:@"type"]) {
72. HTTPLOG(@"任务参数不足");
73. return NO;
74. }
75. //正在处理或等待处理的任务不再接收
76. for (NSDictionary *dicTask in _marrayTaskDic) {
77. //
78. if ([dicParam isEqualToDictionary:[dicTask objectForKey:@"param"]]) {
79. HTTPLOG(@"任务重复:%@", dicParam);
80. return NO;
81. }
82. }
83.
84. HTTPLOG(@"添加新任务,参数:%@", dicParam);
85. NSMutableDictionary *mdicTask = [[NSMutableDictionary alloc] initWithCapacity:3];
86. //设置数据缓存
87. NSMutableData *mdataCache = [[NSMutableData alloc] init];
88. [mdicTask setObject:mdataCache forKey:@"cache"];
89. [mdataCache release];
90. //参数
91. [mdicTask setObject:dicParam forKey:@"param"];
92. //创建HTTP网络连接
93. NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
94. [mdicTask setObject:urlConnection forKey:@"connect"];
95. [urlConnection release];
96. //保存到数组
97. [_marrayTaskDic addObject:mdicTask];
98. [mdicTask release];
99.
100. [self startHTTPConnection];
101. return YES;
102. }
103.
104. //取消网络请求
105. - (BOOL)cancelRequest:(NSDictionary *)dicParam
106. {
107. if (nil == dicParam) {
108. return NO;
109. }
110. //遍历所有任务
111. for (int i = 0; i < _marrayTaskDic.count; i++) {
112. //查看任务是否相同
113. NSDictionary *dicTask = [_marrayTaskDic objectAtIndex:i];
114. if ([dicParam isEqualToDictionary:[dicTask objectForKey:@"param"]]) {
115. //取消网络请求
116. NSURLConnection *connect = [dicTask objectForKey:@"connect"];
117. [connect cancel];
118. //从任务队列中删除
119. [_marrayTaskDic removeObjectAtIndex:i];
120. _numberOfHTTPConnection -= 1;
121. return YES;
122. }
123. }
124. return NO;
125. }
126.
127. //清空网络请求
128. - (void)clearRequest
129. {
130. //遍历所有任务
131. for (NSDictionary *dicTask in _marrayTaskDic) {
132. NSURLConnection *connect = [dicTask objectForKey:@"connect"];
133. [connect cancel];
134. //
135. _numberOfHTTPConnection -= 1;
136. }
137. //从任务队列中删除
138. [_marrayTaskDic removeAllObjects];
139. }
140.
141.
142. #pragma mark -
143. #pragma mark NSURLConnectionDataDelegate
144.
145. - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
146. {
147. HTTPLOG(@"网络请求错误:%@", error);
148. //
149. NSDictionary *dicTask = nil;
150. for (int i = 0; i < _marrayTaskDic.count; i++) {
151. NSDictionary *dic = [_marrayTaskDic objectAtIndex:i];
152. //找到网络连接相应的数据字典
153. if ([dic objectForKey:@"connect"] == connection) {
154. dicTask = dic;
155. break;
156. }
157. }
158.
159. //
160. if (dicTask) {
161. [dicTask retain];
162. //删除
163. [_marrayTaskDic removeObject:dicTask];
164. NSDictionary *dicParam = [dicTask objectForKey:@"param"];
165. if ([_delegate respondsToSelector:@selector(httpConnect:error:with:)]) {
166. [_delegate httpConnect:self error:error with:dicParam];
167. }
168. [dicTask release];
169. _numberOfHTTPConnection -= 1;
170. }
171.
172. //
173. [self startHTTPConnection];
174. }
175.
176. - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
177. {
178. HTTPLOG(@"网络请求收到响应");
179. //
180. NSDictionary *dicTask = nil;
181. for (int i = 0; i < _marrayTaskDic.count; i++) {
182. NSDictionary *dic = [_marrayTaskDic objectAtIndex:i];
183. //找到网络连接相应的数据字典
184. if ([dic objectForKey:@"connect"] == connection) {
185. dicTask = dic;
186. break;
187. }
188. }
189. //
190. if ([response isMemberOfClass:NSHTTPURLResponse.class]) {
191. NSHTTPURLResponse *responseHTTP = (NSHTTPURLResponse *)response;
192. NSUInteger statusCode = responseHTTP.statusCode;
193. NSDictionary *dicAllHeaderFields = responseHTTP.allHeaderFields;
194. NSDictionary *dicParam = [dicTask objectForKey:@"param"];
195. //收到服务器返回的HTTP信息头
196. SEL receiveResponse = @selector(httpConnect:receiveResponseWithStatusCode:andAllHeaderFields:with:);
197. if ([self.delegate respondsToSelector:receiveResponse]) {
198. [self.delegate httpConnect:self receiveResponseWithStatusCode:statusCode
199. andAllHeaderFields:dicAllHeaderFields with:dicParam];
200. }
201. }
202. }
203.
204. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
205. {
206. HTTPLOG(@"网络请求收到数据");
207. //
208. NSDictionary *dicTask = nil;
209. for (int i = 0; i < _marrayTaskDic.count; i++) {
210. NSDictionary *dic = [_marrayTaskDic objectAtIndex:i];
211. //找到网络连接相应的数据字典
212. if ([dic objectForKey:@"connect"] == connection) {
213. dicTask = dic;
214. break;
215. }
216. }
217.
218. //
219. if (dicTask) {
220. //向缓存中添加数据
221. NSMutableData *mdataCache = [dicTask objectForKey:@"cache"];
222. [mdataCache appendData:data];
223. NSDictionary *dicParam = [dicTask objectForKey:@"param"];
224. HTTPLOG(@"该数据的参数:%@", dicParam);
225. //收到部分数据
226. if ([self.delegate respondsToSelector:@selector(httpConnect:receiveData:with:)]) {
227. [self.delegate httpConnect:self receiveData:data with:dicParam];
228. }
229. }
230. HTTPLOG(@"网络请求收到数据并处理完成");
231. }
232.
233. - (void)connectionDidFinishLoading:(NSURLConnection *)connection
234. {
235. HTTPLOG(@"网络请求结束");
236. //
237. NSDictionary *dicTask = nil;
238. for (int i = 0; i < _marrayTaskDic.count; i++) {
239. NSDictionary *dic = [_marrayTaskDic objectAtIndex:i];
240. //找到网络连接相应的数据字典
241. if ([dic objectForKey:@"connect"] == connection) {
242. dicTask = dic;
243. break;
244. }
245. }
246.
247. //
248. if (dicTask) {
249. [dicTask retain];
250. //删除
251. [_marrayTaskDic removeObject:dicTask];
252. NSData *dataCache = [dicTask objectForKey:@"cache"];
253. NSDictionary *dicParam = [dicTask objectForKey:@"param"];
254. if ([_delegate respondsToSelector:@selector(httpConnect:finish:with:)]) {
255. [_delegate httpConnect:self finish:dataCache with:dicParam];
256. }
257. [dicTask release];
258. _numberOfHTTPConnection -= 1;
259. }
260.
261. [self startHTTPConnection];
262. }
263.
264.
265. #pragma mark - Private
266.
267. - (void)startHTTPConnection
268. {
269. if (_numberOfHTTPConnection < MAXNUMBER_HTTPCONNECTION) {
270. if (_numberOfHTTPConnection < _marrayTaskDic.count) {
271. NSDictionary *dicTask = [_marrayTaskDic objectAtIndex:_numberOfHTTPConnection];
272. NSURLConnection *urlConnection = [dicTask objectForKey:@"connect"];
273. [urlConnection start];
274. //
275. _numberOfHTTPConnection += 1;
276. }
277. }
278. HTTPLOG(@"正在处理的网络请求数:%i,等待处理的网络请求:%i",
279. _numberOfHTTPConnection, _marrayTaskDic.count-_numberOfHTTPConnection);
280. }
281.
282. @end www.2cto.com
这个类有四个接口,后两个是取消网络请求的,不必讨论。前两个是发起网络请求的,用的最多的就是这两个接口了。如果只是通过GET方法从服务器取数据,第一个接口足够了。当然也可以用第二个。如果需要用POST方式向服务器发送数据,得用第二个接口。
第一个接口的第一个参数是URL字符串,第二个参数用来区分网络请求的,如果两次请求的第二个参数一样,第二次请求会被过滤掉。这个参数还有一个作用,就是协议回调函数的参数,用来让上层区分网络请求的。
第二个接口的第一个参数是NSURLRequest类型,用来设置网络请求参数的,比如POST、要发送的数据流、HTTP信息头等。第二个参数的作用跟第一个接口的第二个参数一样。
该类对应的协议就不必谈了,大家能看懂的。该类功能的具体实现,大家自己分析。
作者:yjh4866
- 发表评论
-
- 最新评论 更多>>