多種方式實現文件下載功能

(1)使用 NSURLConnection 直接方式緩存

(2)使用 NSURLConnection 代理方式服務器

(3)使用 NSURLSession 直接方式cookie

(4)使用 NSURLSession 代理方式網絡

(5)使用 AFNetworking 方式session

 

附加功能:app

(1)使用 AFNetworking 中的 AFNetworkReachabilityManager 來檢查網絡狀況:異步

  • AFNetworkReachabilityStatusReachableViaWiFi:Wi-Fi 網絡下async

  • AFNetworkReachabilityStatusReachableViaWWAN:2G/3G/4G 蜂窩移動網絡下ide

  • AFNetworkReachabilityStatusNotReachable:未鏈接網絡ui

 

(2)使用 AFNetworking 中的 AFNetworkActivityIndicatorManager 來啓動網絡活動指示器:

1 #import "AFNetworkActivityIndicatorManager.h"
2 
3 //啓動網絡活動指示器;會根據網絡交互狀況,實時顯示或隱藏網絡活動指示器;他經過「通知與消息機制」來實現 [UIApplication sharedApplication].networkActivityIndicatorVisible 的控制
4 [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

 

效果以下:

 

 

 

ViewController.h

1 #import <UIKit/UIKit.h>
2 
3 @interface ViewController : UITableViewController
4 @property (copy, nonatomic) NSArray *arrSampleName;
5 
6 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName;
7 
8 @end 

ViewController.m

 1 #import "ViewController.h"
 2 #import "NSURLConnectionViewController.h"
 3 #import "NSURLConnectionDelegateViewController.h"
 4 #import "NSURLSessionViewController.h"
 5 #import "NSURLSessionDelegateViewController.h"
 6 #import "AFNetworkingViewController.h"
 7 
 8 @interface ViewController ()
 9 - (void)layoutUI;
10 @end
11 
12 @implementation ViewController
13 - (void)viewDidLoad {
14     [super viewDidLoad];
15     
16     [self layoutUI];
17 }
18 
19 - (void)didReceiveMemoryWarning {
20     [super didReceiveMemoryWarning];
21     // Dispose of any resources that can be recreated.
22 }
23 
24 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {
25     if (self = [super initWithStyle:UITableViewStyleGrouped]) {
26         self.navigationItem.title = @"多種方式實現文件下載功能";
27         self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
28         
29         _arrSampleName = arrSampleName;
30     }
31     return self;
32 }
33 
34 - (void)layoutUI {
35 }
36 
37 #pragma mark - UITableViewController相關方法重寫
38 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
39     return 0.1;
40 }
41 
42 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
43     return 1;
44 }
45 
46 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
47     return [_arrSampleName count];
48 }
49 
50 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
51     static NSString *cellIdentifier = @"cell";
52     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
53     if (!cell) {
54         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
55     }
56     cell.textLabel.text = _arrSampleName[indexPath.row];
57     return cell;
58 }
59 
60 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
61     switch (indexPath.row) {
62         case 0: {
63             NSURLConnectionViewController *connectionVC = [NSURLConnectionViewController new];
64             [self.navigationController pushViewController:connectionVC animated:YES];
65             break;
66         }
67         case 1: {
68             NSURLConnectionDelegateViewController *connectionDelegateVC = [NSURLConnectionDelegateViewController new];
69             [self.navigationController pushViewController:connectionDelegateVC animated:YES];
70             break;
71         }
72         case 2: {
73             NSURLSessionViewController *sessionVC = [NSURLSessionViewController new];
74             [self.navigationController pushViewController:sessionVC animated:YES];
75             break;
76         }
77         case 3: {
78             NSURLSessionDelegateViewController *sessionDelegateVC = [NSURLSessionDelegateViewController new];
79             [self.navigationController pushViewController:sessionDelegateVC animated:YES];
80             break;
81         }
82         case 4: {
83             AFNetworkingViewController *networkingVC = [AFNetworkingViewController new];
84             [self.navigationController pushViewController:networkingVC animated:YES];
85             break;
86         }
87         default:
88             break;
89     }
90 }
91 
92 @end 

PrefixHeader.pch

1 #define kFileURLStr @"http://files.cnblogs.com/files/huangjianwu/metro_demo使用Highcharts實現圖表展現.zip"
2 
3 #define kTitleOfNSURLConnection @"使用 NSURLConnection 直接方式"
4 #define kTitleOfNSURLConnectionDelegate @"使用 NSURLConnection 代理方式"
5 #define kTitleOfNSURLSession @"使用 NSURLSession 直接方式"
6 #define kTitleOfNSURLSessionDelegate @"使用 NSURLSession 代理方式"
7 #define kTitleOfAFNetworking @"使用 AFNetworking 方式"
8 
9 #define kApplication [UIApplication sharedApplication] 

UIButton+BeautifulButton.h

 1 #import <UIKit/UIKit.h>
 2 
 3 @interface UIButton (BeautifulButton)
 4 /**
 5  *  根據按鈕文字顏色,返回對應文字顏色的圓角按鈕
 6  *
 7  *  @param tintColor 按鈕文字顏色;nil 的話就爲深灰色
 8  */
 9 - (void)beautifulButton:(UIColor *)tintColor;
10 
11 @end 

UIButton+BeautifulButton.m

 1 #import "UIButton+BeautifulButton.h"
 2 
 3 @implementation UIButton (BeautifulButton)
 4 
 5 - (void)beautifulButton:(UIColor *)tintColor {
 6     self.tintColor = tintColor ?: [UIColor darkGrayColor];
 7     self.layer.masksToBounds = YES;
 8     self.layer.cornerRadius = 10.0;
 9     self.layer.borderColor = [UIColor grayColor].CGColor;
10     self.layer.borderWidth = 1.0;
11 }
12 
13 @end 

NSURLConnectionViewController.h

1 #import <UIKit/UIKit.h>
2 
3 @interface NSURLConnectionViewController : UIViewController
4 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
5 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
6 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
7 
8 @end 

NSURLConnectionViewController.m

 1 #import "NSURLConnectionViewController.h"
 2 #import "UIButton+BeautifulButton.h"
 3 
 4 @interface NSURLConnectionViewController ()
 5 - (void)layoutUI;
 6 - (void)saveDataToDisk:(NSData *)data;
 7 @end
 8 
 9 @implementation NSURLConnectionViewController
10 
11 - (void)viewDidLoad {
12     [super viewDidLoad];
13     
14     [self layoutUI];
15 }
16 
17 - (void)didReceiveMemoryWarning {
18     [super didReceiveMemoryWarning];
19     // Dispose of any resources that can be recreated.
20 }
21 
22 - (void)layoutUI {
23     self.navigationItem.title = kTitleOfNSURLConnection;
24     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
25     
26     [_btnDownloadFile beautifulButton:nil];
27 }
28 
29 - (void)saveDataToDisk:(NSData *)data {
30     //數據接收完保存文件;注意蘋果官方要求:下載數據只能保存在緩存目錄(/Library/Caches)
31     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
32     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
33     [data writeToFile:savePath atomically:YES]; //writeToFile: 方法:若是 savePath 文件存在,他會執行覆蓋
34 }
35 
36 - (IBAction)downloadFile:(id)sender {
37     _lblMessage.text = @"下載中...";
38     
39     NSString *fileURLStr = kFileURLStr;
40     //編碼操做;對應的解碼操做是用 stringByRemovingPercentEncoding 方法
41     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
42     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
43     
44     //建立請求
45     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
46     
47     //建立鏈接;Apple 提供的處理通常請求的兩種方法,他們不須要進行一系列的 NSURLConnectionDataDelegate 委託協議方法操做,簡潔直觀
48     //方法一:發送一個同步請求;不建議使用,由於當前線程是主線程的話,會形成線程阻塞,通常比較少用
49 //    NSURLResponse *response;
50 //    NSError *connectionError;
51 //    NSData *data = [NSURLConnection sendSynchronousRequest:request
52 //                                         returningResponse:&response
53 //                                                     error:&connectionError];
54 //    if (!connectionError) {
55 //        [self saveDataToDisk:data];
56 //        NSLog(@"保存成功");
57 //        
58 //        _lblMessage.text = @"下載完成";
59 //    } else {
60 //        NSLog(@"下載失敗,錯誤信息:%@", connectionError.localizedDescription);
61 //        
62 //        _lblMessage.text = @"下載失敗";
63 //    }
64     
65     //方法二:發送一個異步請求
66     [NSURLConnection sendAsynchronousRequest:request
67                                        queue:[NSOperationQueue mainQueue]
68                            completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
69                                if (!connectionError) {
70                                    [self saveDataToDisk:data];
71                                    NSLog(@"保存成功");
72                                    
73                                    _lblMessage.text = @"下載完成";
74                                    
75                                } else {
76                                    NSLog(@"下載失敗,錯誤信息:%@", connectionError.localizedDescription);
77                                    
78                                    _lblMessage.text = @"下載失敗";
79                                }
80                            }];
81 }
82 
83 @end 

NSURLConnectionViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
 3     <dependencies>
 4         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
 5     </dependencies>
 6     <objects>
 7         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="NSURLConnectionViewController">
 8             <connections>
 9                 <outlet property="btnDownloadFile" destination="mwt-p9-tRE" id="ZVc-6S-ES3"/>
10                 <outlet property="lblFileName" destination="dlB-Qn-eOO" id="NdS-9n-7KX"/>
11                 <outlet property="lblMessage" destination="qlQ-nM-BXU" id="tRe-SR-AQE"/>
12                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
13             </connections>
14         </placeholder>
15         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
16         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
17             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19             <subviews>
20                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="metro_demo使用Highcharts實現圖表展現.zip" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlB-Qn-eOO">
21                     <rect key="frame" x="145" y="104" width="309.5" height="18"/>
22                     <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
23                     <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
24                     <nil key="highlightedColor"/>
25                 </label>
26                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mwt-p9-tRE">
27                     <rect key="frame" x="250" y="520" width="100" height="40"/>
28                     <constraints>
29                         <constraint firstAttribute="width" constant="100" id="I5D-tA-ffH"/>
30                         <constraint firstAttribute="height" constant="40" id="Y8C-D4-IVr"/>
31                     </constraints>
32                     <state key="normal" title="下載">
33                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
34                     </state>
35                     <connections>
36                         <action selector="downloadFile:" destination="-1" eventType="touchUpInside" id="MK4-Yk-IOk"/>
37                     </connections>
38                 </button>
39                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qlQ-nM-BXU">
40                     <rect key="frame" x="145" y="140" width="37.5" height="18"/>
41                     <fontDescription key="fontDescription" type="system" pointSize="15"/>
42                     <color key="textColor" red="0.0" green="0.50196081399917603" blue="1" alpha="1" colorSpace="calibratedRGB"/>
43                     <nil key="highlightedColor"/>
44                     <userDefinedRuntimeAttributes>
45                         <userDefinedRuntimeAttribute type="string" keyPath="text" value=""/>
46                     </userDefinedRuntimeAttributes>
47                 </label>
48             </subviews>
49             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
50             <constraints>
51                 <constraint firstAttribute="centerX" secondItem="dlB-Qn-eOO" secondAttribute="centerX" id="gNK-NO-rth"/>
52                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="104" id="hwU-O2-Fed"/>
53                 <constraint firstAttribute="centerX" secondItem="mwt-p9-tRE" secondAttribute="centerX" id="teN-3t-8Gc"/>
54                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="140" id="w3g-ej-P18"/>
55                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="leading" secondItem="qlQ-nM-BXU" secondAttribute="leading" constant="0.5" id="wMU-pU-z9f"/>
56                 <constraint firstAttribute="bottom" secondItem="mwt-p9-tRE" secondAttribute="bottom" constant="40" id="yBq-He-Jv8"/>
57             </constraints>
58         </view>
59     </objects>
60 </document>
View Code 

NSURLConnectionDelegateViewController.h

 1 #import <UIKit/UIKit.h>
 2 
 3 @interface NSURLConnectionDelegateViewController : UIViewController
 4 @property (strong, nonatomic) NSMutableData *mDataReceive;
 5 @property (assign, nonatomic) NSUInteger totalDataLength;
 6 
 7 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 8 @property (strong, nonatomic) IBOutlet UIProgressView *progVDownloadFile;
 9 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
10 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
11 
12 @end 

NSURLConnectionDelegateViewController.m

  1 #import "NSURLConnectionDelegateViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3 
  4 @interface NSURLConnectionDelegateViewController ()
  5 - (void)layoutUI;
  6 - (BOOL)isExistCacheInMemory:(NSURLRequest *)request;
  7 - (void)updateProgress;
  8 @end
  9 
 10 @implementation NSURLConnectionDelegateViewController
 11 
 12 - (void)viewDidLoad {
 13     [super viewDidLoad];
 14     
 15     [self layoutUI];
 16 }
 17 
 18 - (void)didReceiveMemoryWarning {
 19     [super didReceiveMemoryWarning];
 20     // Dispose of any resources that can be recreated.
 21 }
 22 
 23 - (void)layoutUI {
 24     self.navigationItem.title = kTitleOfNSURLConnectionDelegate;
 25     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 26     
 27     [_btnDownloadFile beautifulButton:nil];
 28 }
 29 
 30 - (BOOL)isExistCacheInMemory:(NSURLRequest *)request {
 31     BOOL isExistCache = NO;
 32     NSURLCache *cache = [NSURLCache sharedURLCache];
 33     [cache setMemoryCapacity:1024 * 1024]; //1M
 34     
 35     NSCachedURLResponse *response = [cache cachedResponseForRequest:request];
 36     if (response != nil) {
 37         NSLog(@"內存中存在對應請求的響應緩存");
 38         isExistCache = YES;
 39     }
 40     return isExistCache;
 41 }
 42 
 43 - (void)updateProgress {
 44     NSUInteger receiveDataLength = _mDataReceive.length;
 45     if (receiveDataLength == _totalDataLength) {
 46         _lblMessage.text = @"下載完成";
 47         kApplication.networkActivityIndicatorVisible = NO;
 48     } else {
 49         _lblMessage.text = @"下載中...";
 50         kApplication.networkActivityIndicatorVisible = YES;
 51         _progVDownloadFile.progress = (float)receiveDataLength / _totalDataLength;
 52     }
 53 }
 54 
 55 - (IBAction)downloadFile:(id)sender {
 56     /*
 57      此例子更多的是但願你們瞭解代理方法接收響應數據的過程,實際開發中也不可能使用這種方法進行文件下載。這種下載有個致命的問題:沒法進行大文件下載。由於代理方法在接收數據時雖然表面看起來是每次讀取一部分響應數據,事實上它只有一次請求而且也只接收了一次服務器響應,只是當響應數據較大時系統會重複調用數據接收方法,每次將已讀取的數據拿出一部分交給數據接收方法而已。在這個過程當中其實早已經將響應數據所有拿到,只是分批交給開發者而已。這樣一來對於幾個G的文件若是進行下載,那麼不用說是真機下載了,就算是模擬器恐怕也是不現實的。
 58      實際開發文件下載的時候不論是經過代理方法仍是靜態方法執行請求和響應,咱們都會分批請求數據,而不是一次性請求數據。假設一個文件有1G,那麼只要每次請求1M的數據,請求1024次也就下載完了。那麼如何讓服務器每次只返回1M的數據呢?
 59      在網絡開發中能夠在請求的頭文件中設置一個Range信息,它表明請求數據的大小。經過這個字段配合服務器端能夠精確的控制每次服務器響應的數據範圍。例如指定bytes=0-1023,而後在服務器端解析Range信息,返回該文件的0到1023之間的數據的數據便可(共1024Byte)。這樣,只要在每次發送請求控制這個頭文件信息就能夠作到分批請求。
 60      固然,爲了讓整個數據保持完整,每次請求的數據都須要逐步追加直到整個文件請求完成。可是如何知道整個文件的大小?其實在此例子經過頭文件信息獲取整個文件大小,他請求整個數據,這樣作對分段下載就沒有任何意義了。所幸在WEB開發中咱們還有另外一種請求方法「HEAD」,經過這種請求服務器只會響應頭信息,其餘數據不會返回給客戶端,這樣一來整個數據的大小也就能夠獲得了。
 61      */
 62     
 63     
 64     NSString *fileURLStr = kFileURLStr;
 65     //編碼操做;對應的解碼操做是用 stringByRemovingPercentEncoding 方法
 66     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 67     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 68     
 69     /*建立請求
 70      cachePolicy:緩存策略
 71      一、NSURLRequestUseProtocolCachePolicy 協議緩存,根據 response 中的 Cache-Control 字段判斷緩存是否有效,若是緩存有效則使用緩存數據不然從新從服務器請求
 72      二、NSURLRequestReloadIgnoringLocalCacheData 不使用緩存,直接請求新數據
 73      三、NSURLRequestReloadIgnoringCacheData 等同於 NSURLRequestReloadIgnoringLocalCacheData
 74      四、NSURLRequestReturnCacheDataElseLoad 直接使用緩存數據不論是否有效,沒有緩存則從新請求
 75      五、NSURLRequestReturnCacheDataDontLoad 直接使用緩存數據不論是否有效,沒有緩存數據則失敗
 76      
 77      timeoutInterval:超時時間設置(默認60s)
 78      */
 79     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:fileURL
 80                                                   cachePolicy:NSURLRequestUseProtocolCachePolicy
 81                                               timeoutInterval:60.0];
 82     if ([self isExistCacheInMemory:request]) {
 83         request = [[NSURLRequest alloc] initWithURL:fileURL
 84                                         cachePolicy:NSURLRequestReturnCacheDataDontLoad
 85                                     timeoutInterval:60.0];
 86     }
 87     
 88     //建立鏈接,異步操做
 89     NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
 90                                                                   delegate:self];
 91     [connection start]; //啓動鏈接
 92 }
 93 
 94 #pragma mark - NSURLConnectionDataDelegate
 95 - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {
 96     NSLog(@"即將發送請求");
 97     
 98     return request;
 99 }
100 
101 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
102     NSLog(@"已經接收到響應");
103     
104     _mDataReceive = [NSMutableData new];
105     _progVDownloadFile.progress = 0.0;
106     
107     //經過響應頭中的 Content-Length 獲取到整個響應的總長度
108     /*
109      {
110      "Accept-Ranges" = bytes;
111      "Cache-Control" = "max-age=7776000";
112      "Content-Length" = 592441;
113      "Content-Type" = "application/x-zip-compressed";
114      Date = "Wed, 02 Sep 2015 13:17:01 GMT";
115      Etag = "\"d8f617371f9cd01:0\"";
116      "Last-Modified" = "Mon, 01 Jun 2015 03:58:27 GMT";
117      Server = "Microsoft-IIS/7.5";
118      "X-Powered-By" = "ASP.NET";
119      }
120      */
121     NSDictionary *dicHeaderField = [(NSHTTPURLResponse *)response allHeaderFields];
122     _totalDataLength = [[dicHeaderField objectForKey:@"Content-Length"] integerValue];
123 }
124 
125 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
126     NSLog(@"已經接收到響應數據,數據長度爲%lu字節...", (unsigned long)[data length]);
127     
128     [_mDataReceive appendData:data]; //連續接收數據
129     [self updateProgress]; //連續更新進度條
130 }
131 
132 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
133     NSLog(@"已經接收完全部響應數據");
134     
135     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
136     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
137     [_mDataReceive writeToFile:savePath atomically:YES];
138 }
139 
140 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
141     //若是鏈接超時或者鏈接地址錯誤可能就會報錯
142     NSLog(@"鏈接錯誤,錯誤信息:%@", error.localizedDescription);
143     
144     _lblMessage.text = @"鏈接錯誤";
145 }
146 
147 @end

NSURLConnectionDelegateViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
 3     <dependencies>
 4         <deployment identifier="iOS"/>
 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
 6     </dependencies>
 7     <objects>
 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="NSURLConnectionDelegateViewController">
 9             <connections>
10                 <outlet property="btnDownloadFile" destination="mwt-p9-tRE" id="ZVc-6S-ES3"/>
11                 <outlet property="lblFileName" destination="dlB-Qn-eOO" id="vJk-jh-Y2c"/>
12                 <outlet property="lblMessage" destination="qlQ-nM-BXU" id="tRe-SR-AQE"/>
13                 <outlet property="progVDownloadFile" destination="Me3-m2-iC4" id="PtK-m7-j5N"/>
14                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
15             </connections>
16         </placeholder>
17         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
18         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
19             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
20             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
21             <subviews>
22                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="metro_demo使用Highcharts實現圖表展現.zip" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlB-Qn-eOO">
23                     <rect key="frame" x="145" y="104" width="309.5" height="18"/>
24                     <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
25                     <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
26                     <nil key="highlightedColor"/>
27                 </label>
28                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mwt-p9-tRE">
29                     <rect key="frame" x="250" y="520" width="100" height="40"/>
30                     <constraints>
31                         <constraint firstAttribute="width" constant="100" id="I5D-tA-ffH"/>
32                         <constraint firstAttribute="height" constant="40" id="Y8C-D4-IVr"/>
33                     </constraints>
34                     <state key="normal" title="下載">
35                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
36                     </state>
37                     <connections>
38                         <action selector="downloadFile:" destination="-1" eventType="touchUpInside" id="iGc-6N-bsZ"/>
39                     </connections>
40                 </button>
41                 <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Me3-m2-iC4">
42                     <rect key="frame" x="145" y="160" width="310" height="2"/>
43                     <constraints>
44                         <constraint firstAttribute="height" constant="2" id="I50-Zx-DwT"/>
45                         <constraint firstAttribute="width" constant="310" id="wdS-eD-Tkc"/>
46                     </constraints>
47                 </progressView>
48                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qlQ-nM-BXU">
49                     <rect key="frame" x="145" y="180" width="37.5" height="18"/>
50                     <fontDescription key="fontDescription" type="system" pointSize="15"/>
51                     <color key="textColor" red="0.0" green="0.50196081399917603" blue="1" alpha="1" colorSpace="calibratedRGB"/>
52                     <nil key="highlightedColor"/>
53                     <userDefinedRuntimeAttributes>
54                         <userDefinedRuntimeAttribute type="string" keyPath="text" value=""/>
55                     </userDefinedRuntimeAttributes>
56                 </label>
57             </subviews>
58             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
59             <constraints>
60                 <constraint firstAttribute="centerX" secondItem="Me3-m2-iC4" secondAttribute="centerX" id="Ya8-bM-TaA"/>
61                 <constraint firstItem="Me3-m2-iC4" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="160" id="bOY-B5-is2"/>
62                 <constraint firstAttribute="centerX" secondItem="dlB-Qn-eOO" secondAttribute="centerX" id="gNK-NO-rth"/>
63                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="104" id="hwU-O2-Fed"/>
64                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="leading" secondItem="Me3-m2-iC4" secondAttribute="leading" id="lus-oi-9SA"/>
65                 <constraint firstAttribute="centerX" secondItem="mwt-p9-tRE" secondAttribute="centerX" id="teN-3t-8Gc"/>
66                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="180" id="w3g-ej-P18"/>
67                 <constraint firstAttribute="bottom" secondItem="mwt-p9-tRE" secondAttribute="bottom" constant="40" id="yBq-He-Jv8"/>
68             </constraints>
69         </view>
70     </objects>
71 </document>
View Code

NSURLSessionViewController.h

1 #import <UIKit/UIKit.h>
2 
3 @interface NSURLSessionViewController : UIViewController
4 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
5 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
6 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
7 
8 @end 

NSURLSessionViewController.m

  1 #import "NSURLSessionViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3 
  4 @interface NSURLSessionViewController ()
  5 - (void)layoutUI;
  6 @end
  7 
  8 @implementation NSURLSessionViewController
  9 
 10 - (void)viewDidLoad {
 11     [super viewDidLoad];
 12     
 13     [self layoutUI];
 14 }
 15 
 16 - (void)didReceiveMemoryWarning {
 17     [super didReceiveMemoryWarning];
 18     // Dispose of any resources that can be recreated.
 19 }
 20 
 21 - (void)layoutUI {
 22     self.navigationItem.title = kTitleOfNSURLSession;
 23     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 24     
 25     [_btnDownloadFile beautifulButton:nil];
 26 }
 27 
 28 - (IBAction)downloadFile:(id)sender {
 29     _lblMessage.text = @"下載中...";
 30     
 31     NSString *fileURLStr = kFileURLStr;
 32     //編碼操做;對應的解碼操做是用 stringByRemovingPercentEncoding 方法
 33     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 34     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 35     
 36     //建立請求
 37     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 38     
 39     //建立會話(這裏使用了一個全局會話)
 40     NSURLSession *session = [NSURLSession sharedSession];
 41     
 42     //建立下載任務,而且啓動他;在非主線程中執行
 43     NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
 44         __block void (^updateUI)(); //聲明用於主線程更新 UI 的代碼塊
 45         
 46         if (!error) {
 47             NSLog(@"下載後的臨時保存路徑:%@", location);
 48             
 49             NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 50             savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
 51             NSURL *saveURL = [NSURL fileURLWithPath:savePath];
 52             NSError *saveError;
 53             NSFileManager *fileManager = [NSFileManager defaultManager];
 54             //判斷是否存在舊的目標文件,若是存在就先移除;避免沒法複製問題
 55             if ([fileManager fileExistsAtPath:savePath]) {
 56                 [fileManager removeItemAtPath:savePath error:&saveError];
 57                 if (saveError) {
 58                     NSLog(@"移除舊的目標文件失敗,錯誤信息:%@", saveError.localizedDescription);
 59                     
 60                     updateUI = ^ {
 61                         _lblMessage.text = @"下載失敗";
 62                     };
 63                 }
 64             }
 65             if (!saveError) {
 66                 //把源文件複製到目標文件,當目標文件存在時,會拋出一個錯誤到 error 參數指向的對象實例
 67                 //方法一(path 不能有 file:// 前綴)
 68                 //                [fileManager copyItemAtPath:[location path]
 69                 //                                     toPath:savePath
 70                 //                                      error:&saveError];
 71                 
 72                 //方法二
 73                 [fileManager copyItemAtURL:location
 74                                      toURL:saveURL
 75                                      error:&saveError];
 76                 
 77                 if (!saveError) {
 78                     NSLog(@"保存成功");
 79                     
 80                     updateUI = ^ {
 81                         _lblMessage.text = @"下載完成";
 82                     };
 83                 } else {
 84                     NSLog(@"保存失敗,錯誤信息:%@", saveError.localizedDescription);
 85                     
 86                     updateUI = ^ {
 87                         _lblMessage.text = @"下載失敗";
 88                     };
 89                 }
 90             }
 91             
 92         } else {
 93             NSLog(@"下載失敗,錯誤信息:%@", error.localizedDescription);
 94             
 95             updateUI = ^ {
 96                 _lblMessage.text = @"下載失敗";
 97             };
 98         }
 99         
100         dispatch_async(dispatch_get_main_queue(), updateUI); //使用主隊列異步方式(主線程)執行更新 UI 的代碼塊
101     }];
102     [downloadTask resume]; //恢復線程,啓動任務
103 }
104 
105 @end 

NSURLSessionViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
 3     <dependencies>
 4         <deployment identifier="iOS"/>
 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
 6     </dependencies>
 7     <objects>
 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="NSURLSessionViewController">
 9             <connections>
10                 <outlet property="btnDownloadFile" destination="mwt-p9-tRE" id="ZVc-6S-ES3"/>
11                 <outlet property="lblFileName" destination="dlB-Qn-eOO" id="NdS-9n-7KX"/>
12                 <outlet property="lblMessage" destination="qlQ-nM-BXU" id="tRe-SR-AQE"/>
13                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
14             </connections>
15         </placeholder>
16         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
17         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
18             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
19             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
20             <subviews>
21                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="metro_demo使用Highcharts實現圖表展現.zip" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlB-Qn-eOO">
22                     <rect key="frame" x="145" y="104" width="309.5" height="18"/>
23                     <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
24                     <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
25                     <nil key="highlightedColor"/>
26                 </label>
27                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mwt-p9-tRE">
28                     <rect key="frame" x="250" y="520" width="100" height="40"/>
29                     <constraints>
30                         <constraint firstAttribute="width" constant="100" id="I5D-tA-ffH"/>
31                         <constraint firstAttribute="height" constant="40" id="Y8C-D4-IVr"/>
32                     </constraints>
33                     <state key="normal" title="下載">
34                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
35                     </state>
36                     <connections>
37                         <action selector="downloadFile:" destination="-1" eventType="touchUpInside" id="MK4-Yk-IOk"/>
38                     </connections>
39                 </button>
40                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qlQ-nM-BXU">
41                     <rect key="frame" x="145" y="140" width="37.5" height="18"/>
42                     <fontDescription key="fontDescription" type="system" pointSize="15"/>
43                     <color key="textColor" red="0.0" green="0.50196081399917603" blue="1" alpha="1" colorSpace="calibratedRGB"/>
44                     <nil key="highlightedColor"/>
45                     <userDefinedRuntimeAttributes>
46                         <userDefinedRuntimeAttribute type="string" keyPath="text" value=""/>
47                     </userDefinedRuntimeAttributes>
48                 </label>
49             </subviews>
50             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
51             <constraints>
52                 <constraint firstAttribute="centerX" secondItem="dlB-Qn-eOO" secondAttribute="centerX" id="gNK-NO-rth"/>
53                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="104" id="hwU-O2-Fed"/>
54                 <constraint firstAttribute="centerX" secondItem="mwt-p9-tRE" secondAttribute="centerX" id="teN-3t-8Gc"/>
55                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="140" id="w3g-ej-P18"/>
56                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="leading" secondItem="qlQ-nM-BXU" secondAttribute="leading" constant="0.5" id="wMU-pU-z9f"/>
57                 <constraint firstAttribute="bottom" secondItem="mwt-p9-tRE" secondAttribute="bottom" constant="40" id="yBq-He-Jv8"/>
58             </constraints>
59         </view>
60     </objects>
61 </document>
View Code 

NSURLSessionDelegateViewController.h

 1 #import <UIKit/UIKit.h>
 2 
 3 @interface NSURLSessionDelegateViewController : UIViewController <NSURLSessionDownloadDelegate>
 4 @property (strong, nonatomic) NSURLSessionDownloadTask *downloadTask;
 5 
 6 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 7 @property (strong, nonatomic) IBOutlet UIProgressView *progVDownloadFile;
 8 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
 9 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
10 @property (strong, nonatomic) IBOutlet UIButton *btnCancel;
11 @property (strong, nonatomic) IBOutlet UIButton *btnSuspend;
12 @property (strong, nonatomic) IBOutlet UIButton *btnResume;
13 
14 @end 

NSURLSessionDelegateViewController.m

  1 #import "NSURLSessionDelegateViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3 
  4 @interface NSURLSessionDelegateViewController ()
  5 - (void)layoutUI;
  6 - (NSURLSession *)defaultSession;
  7 - (NSURLSession *)backgroundSession;
  8 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength;
  9 @end
 10 
 11 @implementation NSURLSessionDelegateViewController
 12 
 13 - (void)viewDidLoad {
 14     [super viewDidLoad];
 15     
 16     [self layoutUI];
 17 }
 18 
 19 - (void)didReceiveMemoryWarning {
 20     [super didReceiveMemoryWarning];
 21     // Dispose of any resources that can be recreated.
 22 }
 23 
 24 - (void)layoutUI {
 25     self.navigationItem.title = kTitleOfNSURLSessionDelegate;
 26     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 27     
 28     [_btnDownloadFile beautifulButton:nil];
 29     [_btnCancel beautifulButton:[UIColor redColor]];
 30     [_btnSuspend beautifulButton:[UIColor purpleColor]];
 31     [_btnResume beautifulButton:[UIColor orangeColor]];
 32 }
 33 
 34 - (NSURLSession *)defaultSession {
 35     /*
 36      NSURLSession 支持進程三種會話:
 37      一、defaultSessionConfiguration:進程內會話(默認會話),用硬盤來緩存數據。
 38      二、ephemeralSessionConfiguration:臨時的進程內會話(內存),不會將 cookie、緩存儲存到本地,只會放到內存中,當應用程序退出後數據也會消失。
 39      三、backgroundSessionConfiguration:後臺會話,相比默認會話,該會話會在後臺開啓一個線程進行網絡數據處理。
 40      */
 41 
 42     //建立會話配置「進程內會話」
 43     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
 44     sessionConfiguration.timeoutIntervalForRequest = 60.0; //請求超時時間;默認爲60秒
 45     sessionConfiguration.allowsCellularAccess = YES; //是否容許蜂窩網絡訪問(2G/3G/4G)
 46     sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多鏈接數;在 iOS 中默認值爲4
 47     
 48     //建立會話
 49     NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration
 50                                                           delegate:self
 51                                                      delegateQueue:nil];
 52     return session;
 53 }
 54 
 55 - (NSURLSession *)backgroundSession {
 56     static NSURLSession *session;
 57     static dispatch_once_t onceToken;
 58     dispatch_once(&onceToken, ^{ //應用程序生命週期內,只執行一次;保證只有一個「後臺會話」
 59         //建立會話配置「後臺會話」
 60         NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"KMDownloadFile.NSURLSessionDelegateViewController"];
 61         sessionConfiguration.timeoutIntervalForRequest = 60.0; //請求超時時間;默認爲60秒
 62         sessionConfiguration.allowsCellularAccess = YES; //是否容許蜂窩網絡訪問(2G/3G/4G)
 63         sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多鏈接數;在 iOS 中默認值爲4
 64         sessionConfiguration.discretionary = YES; //是否自動選擇最佳網絡訪問,僅對「後臺會話」有效
 65         
 66         //建立會話
 67         session = [NSURLSession sessionWithConfiguration:sessionConfiguration
 68                                                 delegate:self
 69                                            delegateQueue:nil];
 70     });
 71     return session;
 72 }
 73 
 74 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; {
 75     dispatch_async(dispatch_get_main_queue(), ^{ //使用主隊列異步方式(主線程)執行更新 UI 操做
 76         if (receiveDataLength == totalDataLength) {
 77             _lblMessage.text = @"下載完成";
 78             kApplication.networkActivityIndicatorVisible = NO;
 79         } else {
 80             _lblMessage.text = @"下載中...";
 81             kApplication.networkActivityIndicatorVisible = YES;
 82             _progVDownloadFile.progress = (float)receiveDataLength / totalDataLength;
 83         }
 84     });
 85 }
 86 
 87 - (IBAction)downloadFile:(id)sender {
 88     NSString *fileURLStr = kFileURLStr;
 89     //編碼操做;對應的解碼操做是用 stringByRemovingPercentEncoding 方法
 90     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 91     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 92     
 93     //建立請求
 94     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 95     
 96     //建立會話「進程內會話」;如要用「後臺會話」就使用自定義的[self backgroundSession] 方法
 97     NSURLSession *session = [self defaultSession];
 98     
 99     //建立下載任務,而且啓動他;在非主線程中執行
100     _downloadTask = [session downloadTaskWithRequest:request];
101     [_downloadTask resume];
102     
103     /*
104      會話任務狀態
105      typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {
106      NSURLSessionTaskStateRunning = 0, //正在執行
107      NSURLSessionTaskStateSuspended = 1, //已掛起
108      NSURLSessionTaskStateCanceling = 2, //正在取消
109      NSURLSessionTaskStateCompleted = 3, //已完成
110      } NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);
111      */
112 }
113 
114 - (IBAction)cancel:(id)sender {
115     [_downloadTask cancel];
116 }
117 
118 - (IBAction)suspend:(id)sender {
119     [_downloadTask suspend];
120     kApplication.networkActivityIndicatorVisible = NO;
121 }
122 
123 - (IBAction)resume:(id)sender {
124     [_downloadTask resume];
125 }
126 
127 #pragma mark - NSURLSessionDownloadDelegate
128 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
129     NSLog(@"已經接收到響應數據,數據長度爲%lld字節...", totalBytesWritten);
130     
131     [self updateProgress:totalBytesWritten totalDataLength:totalBytesExpectedToWrite];
132 }
133 
134 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
135     //下載文件會臨時保存,正常流程下系統最終會自動清除此臨時文件;保存路徑目錄根據會話類型而有所不一樣:
136     //「進程內會話(默認會話)」和「臨時的進程內會話(內存)」,路徑目錄爲:/tmp,能夠經過 NSTemporaryDirectory() 方法獲取
137     //「後臺會話」,路徑目錄爲:/Library/Caches/com.apple.nsurlsessiond/Downloads/com.kenmu.KMDownloadFile
138     NSLog(@"已經接收完全部響應數據,下載後的臨時保存路徑:%@", location);
139     
140     __block void (^updateUI)(); //聲明用於主線程更新 UI 的代碼塊
141     
142     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
143     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
144     NSURL *saveURL = [NSURL fileURLWithPath:savePath];
145     NSError *saveError;
146     NSFileManager *fileManager = [NSFileManager defaultManager];
147     //判斷是否存在舊的目標文件,若是存在就先移除;避免沒法複製問題
148     if ([fileManager fileExistsAtPath:savePath]) {
149         [fileManager removeItemAtPath:savePath error:&saveError];
150         if (saveError) {
151             NSLog(@"移除舊的目標文件失敗,錯誤信息:%@", saveError.localizedDescription);
152             
153             updateUI = ^ {
154                 _lblMessage.text = @"下載失敗";
155             };
156         }
157     }
158     if (!saveError) {
159         //把源文件複製到目標文件,當目標文件存在時,會拋出一個錯誤到 error 參數指向的對象實例
160         //方法一(path 不能有 file:// 前綴)
161         //                [fileManager copyItemAtPath:[location path]
162         //                                     toPath:savePath
163         //                                      error:&saveError];
164         
165         //方法二
166         [fileManager copyItemAtURL:location
167                              toURL:saveURL
168                              error:&saveError];
169         
170         if (!saveError) {
171             NSLog(@"保存成功");
172             
173             updateUI = ^ {
174                 _lblMessage.text = @"下載完成";
175             };
176         } else {
177             NSLog(@"保存失敗,錯誤信息:%@", saveError.localizedDescription);
178             
179             updateUI = ^ {
180                 _lblMessage.text = @"下載失敗";
181             };
182         }
183     }
184     
185     dispatch_async(dispatch_get_main_queue(), updateUI); //使用主隊列異步方式(主線程)執行更新 UI 的代碼塊
186 }
187 
188 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
189     NSLog(@"不管下載成功仍是失敗,最終都會執行一次");
190     
191     if (error) {
192         NSString *desc = error.localizedDescription;
193         NSLog(@"下載失敗,錯誤信息:%@", desc);
194         
195         dispatch_async(dispatch_get_main_queue(), ^{ //使用主隊列異步方式(主線程)執行更新 UI 操做
196             _lblMessage.text = [desc isEqualToString:@"cancelled"] ? @"下載已取消" : @"下載失敗";
197             kApplication.networkActivityIndicatorVisible = NO;
198             _progVDownloadFile.progress = 0.0;
199         });
200     }
201 }
202 
203 @end

NSURLSessionDelegateViewController.xib

  1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
  3     <dependencies>
  4         <deployment identifier="iOS"/>
  5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
  6     </dependencies>
  7     <objects>
  8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="NSURLSessionDelegateViewController">
  9             <connections>
 10                 <outlet property="btnCancel" destination="yMY-kU-iKL" id="QHP-ls-q8P"/>
 11                 <outlet property="btnDownloadFile" destination="mwt-p9-tRE" id="ZVc-6S-ES3"/>
 12                 <outlet property="btnResume" destination="YSM-n6-UM4" id="RyL-54-rFB"/>
 13                 <outlet property="btnSuspend" destination="5kz-pB-9nK" id="1Jj-zV-DXM"/>
 14                 <outlet property="lblFileName" destination="dlB-Qn-eOO" id="vJk-jh-Y2c"/>
 15                 <outlet property="lblMessage" destination="qlQ-nM-BXU" id="tRe-SR-AQE"/>
 16                 <outlet property="progVDownloadFile" destination="Me3-m2-iC4" id="PtK-m7-j5N"/>
 17                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
 18             </connections>
 19         </placeholder>
 20         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
 21         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
 22             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
 23             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
 24             <subviews>
 25                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="metro_demo使用Highcharts實現圖表展現.zip" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlB-Qn-eOO">
 26                     <rect key="frame" x="145" y="104" width="309.5" height="18"/>
 27                     <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
 28                     <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
 29                     <nil key="highlightedColor"/>
 30                 </label>
 31                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mwt-p9-tRE">
 32                     <rect key="frame" x="145" y="520" width="70" height="40"/>
 33                     <constraints>
 34                         <constraint firstAttribute="width" constant="70" id="I5D-tA-ffH"/>
 35                         <constraint firstAttribute="height" constant="40" id="Y8C-D4-IVr"/>
 36                     </constraints>
 37                     <state key="normal" title="下載">
 38                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 39                     </state>
 40                     <connections>
 41                         <action selector="downloadFile:" destination="-1" eventType="touchUpInside" id="iGc-6N-bsZ"/>
 42                     </connections>
 43                 </button>
 44                 <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Me3-m2-iC4">
 45                     <rect key="frame" x="145" y="160" width="310" height="2"/>
 46                     <constraints>
 47                         <constraint firstAttribute="height" constant="2" id="I50-Zx-DwT"/>
 48                         <constraint firstAttribute="width" constant="310" id="wdS-eD-Tkc"/>
 49                     </constraints>
 50                 </progressView>
 51                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qlQ-nM-BXU">
 52                     <rect key="frame" x="145" y="180" width="37.5" height="18"/>
 53                     <fontDescription key="fontDescription" type="system" pointSize="15"/>
 54                     <color key="textColor" red="0.0" green="0.50196081399917603" blue="1" alpha="1" colorSpace="calibratedRGB"/>
 55                     <nil key="highlightedColor"/>
 56                     <userDefinedRuntimeAttributes>
 57                         <userDefinedRuntimeAttribute type="string" keyPath="text" value=""/>
 58                     </userDefinedRuntimeAttributes>
 59                 </label>
 60                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5kz-pB-9nK">
 61                     <rect key="frame" x="305" y="520" width="70" height="40"/>
 62                     <constraints>
 63                         <constraint firstAttribute="width" constant="70" id="IOm-ve-DPG"/>
 64                         <constraint firstAttribute="height" constant="40" id="Kwn-EW-gDl"/>
 65                     </constraints>
 66                     <state key="normal" title="掛起">
 67                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 68                     </state>
 69                     <connections>
 70                         <action selector="suspend:" destination="-1" eventType="touchUpInside" id="O6j-t2-7Lv"/>
 71                     </connections>
 72                 </button>
 73                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YSM-n6-UM4">
 74                     <rect key="frame" x="385" y="520" width="70" height="40"/>
 75                     <constraints>
 76                         <constraint firstAttribute="width" constant="70" id="LhS-5f-cG4"/>
 77                         <constraint firstAttribute="height" constant="40" id="kzz-1h-4DP"/>
 78                     </constraints>
 79                     <state key="normal" title="恢復">
 80                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 81                     </state>
 82                     <connections>
 83                         <action selector="resume:" destination="-1" eventType="touchUpInside" id="ms9-R9-B9B"/>
 84                     </connections>
 85                 </button>
 86                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yMY-kU-iKL">
 87                     <rect key="frame" x="225" y="520" width="70" height="40"/>
 88                     <constraints>
 89                         <constraint firstAttribute="height" constant="40" id="S7b-Pl-qKI"/>
 90                         <constraint firstAttribute="width" constant="70" id="gY7-vp-PUz"/>
 91                     </constraints>
 92                     <state key="normal" title="取消">
 93                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
 94                     </state>
 95                     <connections>
 96                         <action selector="cancel:" destination="-1" eventType="touchUpInside" id="ITC-zg-bfP"/>
 97                     </connections>
 98                 </button>
 99             </subviews>
100             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
101             <constraints>
102                 <constraint firstItem="5kz-pB-9nK" firstAttribute="centerY" secondItem="YSM-n6-UM4" secondAttribute="centerY" id="4zt-gy-k65"/>
103                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="leading" secondItem="mwt-p9-tRE" secondAttribute="leading" id="RYu-qM-O8P"/>
104                 <constraint firstAttribute="centerX" secondItem="Me3-m2-iC4" secondAttribute="centerX" id="Ya8-bM-TaA"/>
105                 <constraint firstItem="Me3-m2-iC4" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="160" id="bOY-B5-is2"/>
106                 <constraint firstItem="yMY-kU-iKL" firstAttribute="centerY" secondItem="5kz-pB-9nK" secondAttribute="centerY" id="dBh-1A-sIk"/>
107                 <constraint firstItem="YSM-n6-UM4" firstAttribute="leading" secondItem="5kz-pB-9nK" secondAttribute="trailing" constant="10" id="fYW-Jv-ro2"/>
108                 <constraint firstAttribute="centerX" secondItem="dlB-Qn-eOO" secondAttribute="centerX" id="gNK-NO-rth"/>
109                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="104" id="hwU-O2-Fed"/>
110                 <constraint firstItem="mwt-p9-tRE" firstAttribute="centerY" secondItem="yMY-kU-iKL" secondAttribute="centerY" id="lGv-fH-Fh7"/>
111                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="leading" secondItem="Me3-m2-iC4" secondAttribute="leading" id="lus-oi-9SA"/>
112                 <constraint firstItem="5kz-pB-9nK" firstAttribute="leading" secondItem="yMY-kU-iKL" secondAttribute="trailing" constant="10" id="oge-T7-1td"/>
113                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="180" id="w3g-ej-P18"/>
114                 <constraint firstItem="yMY-kU-iKL" firstAttribute="leading" secondItem="mwt-p9-tRE" secondAttribute="trailing" constant="10" id="xCX-1F-xOv"/>
115                 <constraint firstAttribute="bottom" secondItem="mwt-p9-tRE" secondAttribute="bottom" constant="40" id="yBq-He-Jv8"/>
116             </constraints>
117         </view>
118     </objects>
119 </document>
View Code 

AFNetworkingViewController.h

 1 #import <UIKit/UIKit.h>
 2 #import "MBProgressHUD.h"
 3 
 4 @interface AFNetworkingViewController : UIViewController
 5 @property (strong, nonatomic) MBProgressHUD *hud;
 6 
 7 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 8 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
 9 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFileByConnection;
10 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFileBySession;
11 
12 @end 

AFNetworkingViewController.m

  1 #import "AFNetworkingViewController.h"
  2 #import "AFNetworking.h"
  3 #import "AFNetworkActivityIndicatorManager.h"
  4 #import "UIButton+BeautifulButton.h"
  5 
  6 @interface AFNetworkingViewController ()
  7 - (void)showAlert:(NSString *)msg;
  8 - (void)checkNetwork;
  9 - (void)layoutUI;
 10 - (NSMutableURLRequest *)downloadRequest;
 11 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile;
 12 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength;
 13 @end
 14 
 15 @implementation AFNetworkingViewController
 16 
 17 - (void)viewDidLoad {
 18     [super viewDidLoad];
 19     
 20     [self layoutUI];
 21 }
 22 
 23 - (void)didReceiveMemoryWarning {
 24     [super didReceiveMemoryWarning];
 25     // Dispose of any resources that can be recreated.
 26 }
 27 
 28 - (void)showAlert:(NSString *)msg {
 29     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"網絡狀況"
 30                                                     message:msg
 31                                                    delegate:self
 32                                           cancelButtonTitle:nil
 33                                           otherButtonTitles:@"肯定", nil];
 34     [alert show];
 35 }
 36 
 37 - (void)checkNetwork {
 38     NSURL *baseURL = [NSURL URLWithString:@"http://www.baidu.com/"];
 39     AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
 40     
 41     NSOperationQueue *operationQueue = manager.operationQueue;
 42     [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
 43         switch (status) {
 44             case AFNetworkReachabilityStatusReachableViaWiFi:
 45                 [self showAlert:@"Wi-Fi 網絡下"];
 46                 [operationQueue setSuspended:NO];
 47                 break;
 48             case AFNetworkReachabilityStatusReachableViaWWAN:
 49                 [self showAlert:@"2G/3G/4G 蜂窩移動網絡下"];
 50                 [operationQueue setSuspended:YES];
 51                 break;
 52             case AFNetworkReachabilityStatusNotReachable:
 53             default:
 54                 [self showAlert:@"未鏈接網絡"];
 55                 [operationQueue setSuspended:YES];
 56                 break;
 57         }
 58     }];
 59     
 60     [manager.reachabilityManager startMonitoring];
 61 }
 62 
 63 - (void)layoutUI {
 64     self.navigationItem.title = kTitleOfAFNetworking;
 65     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 66     
 67     //條件表達式中,「?:」能夠表示在條件不成立的狀況,才使用後者賦值,不然使用用於條件判斷的前者賦值
 68     //如下語句等同於:UIButton *btn = _btnDownloadFileByConnection ? _btnDownloadFileByConnection : [UIButton new];
 69     //在 .NET 中,至關於使用「??」;在 JavaScript 中,至關於使用「||」來實現這種相似的判斷
 70     UIButton *btn = _btnDownloadFileByConnection ?: [UIButton new];
 71     [btn beautifulButton:nil];
 72     [_btnDownloadFileBySession beautifulButton:[UIColor orangeColor]];
 73     
 74     //進度效果
 75     _hud = [[MBProgressHUD alloc] initWithView:self.view];
 76     _hud.mode = MBProgressHUDModeDeterminate;
 77     _hud.labelText = @"下載中...";
 78     [_hud hide:YES];
 79     [self.view addSubview:_hud];
 80     
 81     //檢查網絡狀況
 82     [self checkNetwork];
 83     
 84     //啓動網絡活動指示器;會根據網絡交互狀況,實時顯示或隱藏網絡活動指示器;他經過「通知與消息機制」來實現 [UIApplication sharedApplication].networkActivityIndicatorVisible 的控制
 85     [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
 86 }
 87 
 88 - (NSMutableURLRequest *)downloadRequest {
 89     NSString *fileURLStr = kFileURLStr;
 90     //編碼操做;對應的解碼操做是用 stringByRemovingPercentEncoding 方法
 91     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 92     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 93     
 94     //建立請求
 95     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 96     return request;
 97 }
 98 
 99 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile {
100     NSString *fileName = response ? [response suggestedFilename] : _lblFileName.text;
101     
102     //方法一
103 //    NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
104 //    savePath = [savePath stringByAppendingPathComponent:fileName];
105 //    NSURL *saveURL = [NSURL fileURLWithPath:savePath];
106     
107     //方法二
108     NSURL *saveURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
109     saveURL = [saveURL URLByAppendingPathComponent:fileName];
110     NSString *savePath = [saveURL path];
111     
112     if (deleteExistFile) {
113         NSError *saveError;
114         NSFileManager *fileManager = [NSFileManager defaultManager];
115         //判斷是否存在舊的目標文件,若是存在就先移除;避免沒法複製問題
116         if ([fileManager fileExistsAtPath:savePath]) {
117             [fileManager removeItemAtPath:savePath error:&saveError];
118             if (saveError) {
119                 NSLog(@"移除舊的目標文件失敗,錯誤信息:%@", saveError.localizedDescription);
120             }
121         }
122     }
123     
124     return saveURL;
125 }
126 
127 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; {
128     dispatch_async(dispatch_get_main_queue(), ^{ //使用主隊列異步方式(主線程)執行更新 UI 操做
129         _hud.progress = (float)receiveDataLength / totalDataLength;
130         
131         if (receiveDataLength == totalDataLength) {
132             _lblMessage.text =  receiveDataLength < 0 ? @"下載失敗" : @"下載完成";
133             //kApplication.networkActivityIndicatorVisible = NO;
134             [_hud hide:YES];
135         } else {
136             _lblMessage.text = @"下載中...";
137             //kApplication.networkActivityIndicatorVisible = YES;
138             [_hud show:YES];
139         }
140     });
141 }
142 
143 - (IBAction)downloadFileByConnection:(id)sender {
144     //建立請求
145     NSMutableURLRequest *request = [self downloadRequest];
146     
147     //建立請求操做
148     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
149     NSString *savePath = [[self saveURL:nil deleteExistFile:NO] path];
150     
151     [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
152         NSLog(@"已經接收到響應數據,數據長度爲%lld字節...", totalBytesRead);
153         
154         [self updateProgress:totalBytesRead totalDataLength:totalBytesExpectedToRead];
155     }];
156     
157     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
158         NSLog(@"已經接收完全部響應數據");
159         
160         NSData *data = (NSData *)responseObject;
161         [data writeToFile:savePath atomically:YES]; //responseObject 的對象類型是 NSData
162         
163         [self updateProgress:100 totalDataLength:100];
164     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
165         NSLog(@"下載失敗,錯誤信息:%@", error.localizedDescription);
166         
167         [self updateProgress:-1 totalDataLength:-1];
168     }];
169     
170     //啓動請求操做
171     [operation start];
172 }
173 
174 - (IBAction)downloadFileBySession:(id)sender {
175     //建立請求
176     NSMutableURLRequest *request = [self downloadRequest];
177     
178     //建立會話配置「進程內會話」
179     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
180     sessionConfiguration.timeoutIntervalForRequest = 60.0; //請求超時時間;默認爲60秒
181     sessionConfiguration.allowsCellularAccess = YES; //是否容許蜂窩網絡訪問(2G/3G/4G)
182     sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多鏈接數;在 iOS 中默認值爲4
183     
184     //建立會話管理器
185     AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfiguration];
186     
187     //建立會話下載任務,而且啓動他;在非主線程中執行
188     NSURLSessionDownloadTask *task = [sessionManager
189                                       downloadTaskWithRequest:request
190                                       progress:nil
191                                       destination:^ NSURL*(NSURL *targetPath, NSURLResponse *response) {
192                                           //當 sessionManager 調用 setDownloadTaskDidFinishDownloadingBlock: 方法,而且方法代碼塊返回值不爲 nil 時(優先級高),下面的兩句代碼是不執行的(優先級低)
193                                           NSLog(@"下載後的臨時保存路徑:%@", targetPath);
194                                           return [self saveURL:response deleteExistFile:YES];
195                                       } completionHandler:^ (NSURLResponse *response, NSURL *filePath, NSError *error) {
196                                           if (!error) {
197                                               NSLog(@"下載後的保存路徑:%@", filePath); //爲上面代碼塊返回的路徑
198                                               
199                                               [self updateProgress:100 totalDataLength:100];
200                                           } else {
201                                               NSLog(@"下載失敗,錯誤信息:%@", error.localizedDescription);
202                                               
203                                               [self updateProgress:-1 totalDataLength:-1];
204                                           }
205                                           
206                                           [_hud hide:YES];
207                                       }];
208     
209     //相似 NSURLSessionDownloadDelegate 的方法操做
210     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
211     [sessionManager setDownloadTaskDidWriteDataBlock:^ (NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
212         NSLog(@"已經接收到響應數據,數據長度爲%lld字節...", totalBytesWritten);
213         
214         [self updateProgress:totalBytesWritten totalDataLength:totalBytesExpectedToWrite];
215     }];
216     
217     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;
218     [sessionManager setDownloadTaskDidFinishDownloadingBlock:^ NSURL*(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {
219         NSLog(@"已經接收完全部響應數據,下載後的臨時保存路徑:%@", location);
220         return [self saveURL:nil deleteExistFile:YES];
221     }];
222     
223     [task resume];
224 }
225 
226 @end

AFNetworkingViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
 3     <dependencies>
 4         <deployment identifier="iOS"/>
 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
 6     </dependencies>
 7     <objects>
 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AFNetworkingViewController">
 9             <connections>
10                 <outlet property="btnDownloadFileByConnection" destination="IkH-un-SOz" id="gDd-6X-uxU"/>
11                 <outlet property="btnDownloadFileBySession" destination="mwt-p9-tRE" id="5Qk-Zm-V3w"/>
12                 <outlet property="lblFileName" destination="dlB-Qn-eOO" id="NdS-9n-7KX"/>
13                 <outlet property="lblMessage" destination="qlQ-nM-BXU" id="tRe-SR-AQE"/>
14                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
15             </connections>
16         </placeholder>
17         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
18         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
19             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
20             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
21             <subviews>
22                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="metro_demo使用Highcharts實現圖表展現.zip" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlB-Qn-eOO">
23                     <rect key="frame" x="145" y="104" width="309.5" height="18"/>
24                     <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
25                     <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
26                     <nil key="highlightedColor"/>
27                 </label>
28                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mwt-p9-tRE">
29                     <rect key="frame" x="175" y="520" width="250" height="40"/>
30                     <constraints>
31                         <constraint firstAttribute="width" constant="250" id="I5D-tA-ffH"/>
32                         <constraint firstAttribute="height" constant="40" id="Y8C-D4-IVr"/>
33                     </constraints>
34                     <state key="normal" title="基於 NSURLSession 的下載">
35                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
36                     </state>
37                     <connections>
38                         <action selector="downloadFileBySession:" destination="-1" eventType="touchUpInside" id="z6s-cq-dag"/>
39                     </connections>
40                 </button>
41                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qlQ-nM-BXU">
42                     <rect key="frame" x="145" y="140" width="37.5" height="18"/>
43                     <fontDescription key="fontDescription" type="system" pointSize="15"/>
44                     <color key="textColor" red="0.0" green="0.50196081399917603" blue="1" alpha="1" colorSpace="calibratedRGB"/>
45                     <nil key="highlightedColor"/>
46                     <userDefinedRuntimeAttributes>
47                         <userDefinedRuntimeAttribute type="string" keyPath="text" value=""/>
48                     </userDefinedRuntimeAttributes>
49                 </label>
50                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IkH-un-SOz">
51                     <rect key="frame" x="174" y="460" width="250" height="40"/>
52                     <constraints>
53                         <constraint firstAttribute="width" constant="250" id="3a7-Og-iWa"/>
54                         <constraint firstAttribute="height" constant="40" id="mc0-yK-hWE"/>
55                     </constraints>
56                     <state key="normal" title="基於 NSURLConnection 的下載">
57                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
58                     </state>
59                     <connections>
60                         <action selector="downloadFileByConnection:" destination="-1" eventType="touchUpInside" id="1ko-jP-kCo"/>
61                     </connections>
62                 </button>
63             </subviews>
64             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
65             <constraints>
66                 <constraint firstItem="mwt-p9-tRE" firstAttribute="top" secondItem="IkH-un-SOz" secondAttribute="bottom" constant="20" id="Sye-JW-gux"/>
67                 <constraint firstAttribute="centerX" secondItem="dlB-Qn-eOO" secondAttribute="centerX" id="gNK-NO-rth"/>
68                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="104" id="hwU-O2-Fed"/>
69                 <constraint firstAttribute="centerX" secondItem="IkH-un-SOz" secondAttribute="centerX" constant="1" id="lF1-Yf-Axs"/>
70                 <constraint firstAttribute="centerX" secondItem="mwt-p9-tRE" secondAttribute="centerX" id="teN-3t-8Gc"/>
71                 <constraint firstItem="qlQ-nM-BXU" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="140" id="w3g-ej-P18"/>
72                 <constraint firstItem="dlB-Qn-eOO" firstAttribute="leading" secondItem="qlQ-nM-BXU" secondAttribute="leading" constant="0.5" id="wMU-pU-z9f"/>
73                 <constraint firstAttribute="bottom" secondItem="mwt-p9-tRE" secondAttribute="bottom" constant="40" id="yBq-He-Jv8"/>
74             </constraints>
75         </view>
76     </objects>
77 </document>
View Cod 

AppDelegate.h

1 #import <UIKit/UIKit.h>
2 
3 @interface AppDelegate : UIResponder <UIApplicationDelegate>
4 
5 @property (strong, nonatomic) UIWindow *window;
6 @property (strong, nonatomic) UINavigationController *navigationController;
7 
8 @end 

AppDelegate.m

 1 #import "AppDelegate.h"
 2 #import "ViewController.h"
 3 
 4 @interface AppDelegate ()
 5 
 6 @end
 7 
 8 @implementation AppDelegate
 9 
10 
11 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
12     _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
13     ViewController *viewController = [[ViewController alloc]
14                                       initWithSampleNameArray:@[ kTitleOfNSURLConnection,
15                                                                  kTitleOfNSURLConnectionDelegate,
16                                                                  kTitleOfNSURLSession,
17                                                                  kTitleOfNSURLSessionDelegate,
18                                                                  kTitleOfAFNetworking]];
19     _navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
20     _window.rootViewController = _navigationController;
21     //[_window addSubview:_navigationController.view]; //當_window.rootViewController關聯時,這一句無關緊要
22     [_window makeKeyAndVisible];
23     return YES;
24 }
25 
26 - (void)applicationWillResignActive:(UIApplication *)application {
27 }
28 
29 - (void)applicationDidEnterBackground:(UIApplication *)application {
30 }
31 
32 - (void)applicationWillEnterForeground:(UIApplication *)application {
33 }
34 
35 - (void)applicationDidBecomeActive:(UIApplication *)application {
36 }
37 
38 - (void)applicationWillTerminate:(UIApplication *)application {
39 }
40 
41 @end
相關文章
相關標籤/搜索