給NSURLConnection包一層更簡單的接口,就能夠減小每次的下載工做,省去大量的重複。
XYConnection繼承自NSURLConnection,這個類管理臨時的數據結構,並管理一般由控制器對象負責的進度,這樣發起調用的代碼只需在下載完成,數據準備好以後進行響應就好了。也建立了可選的掛鉤機制,能夠見識下載進度。
包含的其餘信息有: 數據結構
1,目標URL
2,起始NSURLRequest
3,預計的下載大小
4,目前一完成的下載量 app
代碼,XYConnection.h: 大數據
#import <Foundation/Foundation.h> @class XYConnection; typedef void (^XYConnectionProgressBlock)(XYConnection *connection); typedef void (^XYConnectionCompletionBlock)(XYConnection *connection, NSError *error); @interface XYConnection : NSURLConnection<NSURLConnectionDataDelegate> @property (nonatomic, copy, readonly) NSURL *url; @property (nonatomic, copy, readonly) NSURLRequest *urlRequest; @property (nonatomic, assign, readonly) NSInteger contentLength; @property (nonatomic, retain, readonly) NSMutableData *downloadData; @property (nonatomic, assign, readonly) float percentComplete; @property (nonatomic, assign) NSUInteger progressThreshold; + (id)connectionWithURL:(NSURL *)requestURL progressBlock:(XYConnectionProgressBlock)progress completionBlock:(XYConnectionCompletionBlock)completion; + (id)connectionWithRequest:(NSURLRequest *)request progressBlock:(XYConnectionProgressBlock)progress completionBlock:(XYConnectionCompletionBlock)completion; - (id)initWithURL:(NSURL *)requestURL progressBlock:(XYConnectionProgressBlock)progress completionBlock:(XYConnectionCompletionBlock)completion; - (id)initWithRequest:(NSURLRequest *)request progressBlock:(XYConnectionProgressBlock)progress completionBlock:(XYConnectionCompletionBlock)completion; - (void)start; - (void)stop; @end
咱們可直接傳入目標URL和可選的用於處理下載進度、完成、失敗的Block,建立鏈接。-start和-stop方法用於顯式的開始或取消鏈接。Block部分,一個報告進度的增長,另外一個報告完成或失敗。 atom
contentLength屬性表示鏈接的相應頭中的Content-Length值。這個值是在接收到標準的NSURLContent委託方法-connection:didReceiveResponse:的調用時設置的。 url
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ if ([response isKindOfClass:[NSHTTPURLResponse class]]){ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if ([httpResponse statusCode] == 200){ NSDictionary *header = [httpResponse allHeaderFields]; NSString *contentLen = [header valueForKey:@"Content-Lenght"]; NSInteger length = self.contentLength = [contentLen integerValue]; self.downloadData = [NSMutableData dataWithCapacity:length]; } } }
使用這個值和已下載的數據量計算percentComplete屬性 code
- (float)percentComplete{ if (self.contentLength <= 0) return 0; return (([self.downloadData length] * 1.0f) / self.contentLength) * 100; }
每當percentComplete達到制定的progressThreshold的倍數時,報告進的的Block就會被調用。 對象
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ [self.downloadData appendData:data]; float pctComplete = floorf([self percentComplete]); if ((pctComplete - self.previousMilestone) >= self.progressThreshold){ self.previousMilestone = pctComplete; if (self.progressBlock) self.progressBlock(self); } }
注意,對於大數據量的下載,須要準備一個NSInputStream,拿到數據時就把它寫到固態硬盤,以防止內存不足。 繼承
還有關於內存管理,本博文的完整代碼在內存管理上作的不太好,能改進的地方請指正。 接口