ASIHTTPRequest足夠瞭嗎? – iPhone手機開發技術文章 iPhone軟體開發教學課程

 大傢都知道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.aiwalls.com

        這個類有四個接口,後兩個是取消網絡請求的,不必討論。前兩個是發起網絡請求的,用的最多的就是這兩個接口瞭。如果隻是通過GET方法從服務器取數據,第一個接口足夠瞭。當然也可以用第二個。如果需要用POST方式向服務器發送數據,得用第二個接口。
        第一個接口的第一個參數是URL字符串,第二個參數用來區分網絡請求的,如果兩次請求的第二個參數一樣,第二次請求會被過濾掉。這個參數還有一個作用,就是協議回調函數的參數,用來讓上層區分網絡請求的。
        第二個接口的第一個參數是NSURLRequest類型,用來設置網絡請求參數的,比如POST、要發送的數據流、HTTP信息頭等。第二個參數的作用跟第一個接口的第二個參數一樣。
        該類對應的協議就不必談瞭,大傢能看懂的。該類功能的具體實現,大傢自己分析。

 作者:yjh4866

發佈留言