当前位置: 代码迷 >> Iphone >> 多种形式实现文件下载功能
  详细解决方案

多种形式实现文件下载功能

热度:174   发布时间:2016-04-25 05:32:30.0
多种方式实现文件下载功能

(1)使用 NSURLConnection 直接方式

(2)使用 NSURLConnection 代理方式

(3)使用 NSURLSession 直接方式

(4)使用 NSURLSession 代理方式

(5)使用 AFNetworking 方式

 

附加功能:

使用 AFNetworking 中的 AFNetworkReachabilityManager 相关操作来检查网络情况:

  1. AFNetworkReachabilityStatusReachableViaWiFi:Wi-Fi 网络下

  2. AFNetworkReachabilityStatusReachableViaWWAN:2G/3G/4G 蜂窝移动网络下

  3. AFNetworkReachabilityStatusNotReachable:未连接网络

 

效果如下:

 

 

 

ViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface ViewController : UITableViewController4 @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 @end11 12 @implementation ViewController13 - (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 : UIViewController4 @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 NSURLConnectionViewController10 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:request52 //                                         returningResponse:&response53 //                                                     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:request67                                        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      1、NSURLRequestUseProtocolCachePolicy 协议缓存,根据 response 中的 Cache-Control 字段判断缓存是否有效,如果缓存有效则使用缓存数据否则重新从服务器请求 72      2、NSURLRequestReloadIgnoringLocalCacheData 不使用缓存,直接请求新数据 73      3、NSURLRequestReloadIgnoringCacheData 等同于 NSURLRequestReloadIgnoringLocalCacheData 74      4、NSURLRequestReturnCacheDataElseLoad 直接使用缓存数据不管是否有效,没有缓存则重新请求 75      5、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 : UIViewController4 @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      1、defaultSessionConfiguration:进程内会话(默认会话),用硬盘来缓存数据。 38      2、ephemeralSessionConfiguration:临时的进程内会话(内存),不会将 cookie、缓存储存到本地,只会放到内存中,当应用程序退出后数据也会消失。 39      3、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 - NSURLSessionDownloadDelegate128 - (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.KMDownloadFile138     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:savePath163         //                                      error:&saveError];164         165         //方法二166         [fileManager copyItemAtURL:location167                              toURL:saveURL168                              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 "UIButton+BeautifulButton.h"  4   5 @interface AFNetworkingViewController ()  6 - (void)showAlert:(NSString *)msg;  7 - (void)checkNetwork;  8 - (void)layoutUI;  9 - (NSMutableURLRequest *)downloadRequest; 10 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile; 11 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; 12 @end 13  14 @implementation AFNetworkingViewController 15  16 - (void)viewDidLoad { 17     [super viewDidLoad]; 18      19     [self layoutUI]; 20 } 21  22 - (void)didReceiveMemoryWarning { 23     [super didReceiveMemoryWarning]; 24     // Dispose of any resources that can be recreated. 25 } 26  27 - (void)showAlert:(NSString *)msg { 28     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络情况" 29                                                     message:msg 30                                                    delegate:self 31                                           cancelButtonTitle:nil 32                                           otherButtonTitles:@"确定", nil]; 33     [alert show]; 34 } 35  36 - (void)checkNetwork { 37     NSURL *baseURL = [NSURL URLWithString:@"http://www.baidu.com/"]; 38     AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL]; 39      40     NSOperationQueue *operationQueue = manager.operationQueue; 41     [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { 42         switch (status) { 43             case AFNetworkReachabilityStatusReachableViaWiFi: 44                 [self showAlert:@"Wi-Fi 网络下"]; 45                 [operationQueue setSuspended:NO]; 46                 break; 47             case AFNetworkReachabilityStatusReachableViaWWAN: 48                 [self showAlert:@"2G/3G/4G 蜂窝移动网络下"]; 49                 [operationQueue setSuspended:YES]; 50                 break; 51             case AFNetworkReachabilityStatusNotReachable: 52             default: 53                 [self showAlert:@"未连接网络"]; 54                 [operationQueue setSuspended:YES]; 55                 break; 56         } 57     }]; 58      59     [manager.reachabilityManager startMonitoring]; 60 } 61  62 - (void)layoutUI { 63     self.navigationItem.title = kTitleOfAFNetworking; 64     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000]; 65      66     //条件表达式中,「?:」可以表示在条件不成立的情况,才使用后者赋值,否则使用用于条件判断的前者赋值 67     //以下语句等同于:UIButton *btn = _btnDownloadFileByConnection ? _btnDownloadFileByConnection : [UIButton new]; 68     //在 .NET 中,相当于使用「??」;在 JavaScript 中,相当于使用「||」来实现这种类似的判断 69     UIButton *btn = _btnDownloadFileByConnection ?: [UIButton new]; 70     [btn beautifulButton:nil]; 71     [_btnDownloadFileBySession beautifulButton:[UIColor orangeColor]]; 72      73     //进度效果 74     _hud = [[MBProgressHUD alloc] initWithView:self.view]; 75     _hud.mode = MBProgressHUDModeDeterminate; 76     _hud.labelText = @"下载中..."; 77     [_hud hide:YES]; 78     [self.view addSubview:_hud]; 79      80     //检查网络情况 81     [self checkNetwork]; 82 } 83  84 - (NSMutableURLRequest *)downloadRequest { 85     NSString *fileURLStr = kFileURLStr; 86     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法 87     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 88     NSURL *fileURL = [NSURL URLWithString:fileURLStr]; 89      90     //创建请求 91     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL]; 92     return request; 93 } 94  95 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile { 96     NSString *fileName = response ? [response suggestedFilename] : _lblFileName.text; 97      98     //方法一 99 //    NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];100 //    savePath = [savePath stringByAppendingPathComponent:fileName];101 //    NSURL *saveURL = [NSURL fileURLWithPath:savePath];102     103     //方法二104     NSURL *saveURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];105     saveURL = [saveURL URLByAppendingPathComponent:fileName];106     NSString *savePath = [saveURL path];107     108     if (deleteExistFile) {109         NSError *saveError;110         NSFileManager *fileManager = [NSFileManager defaultManager];111         //判断是否存在旧的目标文件,如果存在就先移除;避免无法复制问题112         if ([fileManager fileExistsAtPath:savePath]) {113             [fileManager removeItemAtPath:savePath error:&saveError];114             if (saveError) {115                 NSLog(@"移除旧的目标文件失败,错误信息:%@", saveError.localizedDescription);116             }117         }118     }119     120     return saveURL;121 }122 123 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; {124     dispatch_async(dispatch_get_main_queue(), ^{ //使用主队列异步方式(主线程)执行更新 UI 操作125         _hud.progress = (float)receiveDataLength / totalDataLength;126         127         if (receiveDataLength == totalDataLength) {128             _lblMessage.text =  receiveDataLength < 0 ? @"下载失败" : @"下载完成";129             kApplication.networkActivityIndicatorVisible = NO;130             [_hud hide:YES];131         } else {132             _lblMessage.text = @"下载中...";133             kApplication.networkActivityIndicatorVisible = YES;134             [_hud show:YES];135         }136     });137 }138 139 - (IBAction)downloadFileByConnection:(id)sender {140     //创建请求141     NSMutableURLRequest *request = [self downloadRequest];142     143     //创建请求操作144     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];145     NSString *savePath = [[self saveURL:nil deleteExistFile:NO] path];146     147     [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {148         NSLog(@"已经接收到响应数据,数据长度为%lld字节...", totalBytesRead);149         150         [self updateProgress:totalBytesRead totalDataLength:totalBytesExpectedToRead];151     }];152     153     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {154         NSLog(@"已经接收完所有响应数据");155         156         NSData *data = (NSData *)responseObject;157         [data writeToFile:savePath atomically:YES]; //responseObject 的对象类型是 NSData158         159         [self updateProgress:100 totalDataLength:100];160     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {161         NSLog(@"下载失败,错误信息:%@", error.localizedDescription);162         163         [self updateProgress:-1 totalDataLength:-1];164     }];165     166     //启动请求操作167     [operation start];168 }169 170 - (IBAction)downloadFileBySession:(id)sender {171     //创建请求172     NSMutableURLRequest *request = [self downloadRequest];173     174     //创建会话配置「进程内会话」175     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];176     sessionConfiguration.timeoutIntervalForRequest = 60.0; //请求超时时间;默认为60秒177     sessionConfiguration.allowsCellularAccess = YES; //是否允许蜂窝网络访问(2G/3G/4G)178     sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多连接数;在 iOS 中默认值为4179     180     //创建会话管理器181     AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfiguration];182     183     //创建会话下载任务,并且启动他;在非主线程中执行184     NSURLSessionDownloadTask *task = [sessionManager185                                       downloadTaskWithRequest:request186                                       progress:nil187                                       destination:^ NSURL*(NSURL *targetPath, NSURLResponse *response) {188                                           //当 sessionManager 调用 setDownloadTaskDidFinishDownloadingBlock: 方法,并且方法代码块返回值不为 nil 时(优先级高),下面的两句代码是不执行的(优先级低)189                                           NSLog(@"下载后的临时保存路径:%@", targetPath);190                                           return [self saveURL:response deleteExistFile:YES];191                                       } completionHandler:^ (NSURLResponse *response, NSURL *filePath, NSError *error) {192                                           if (!error) {193                                               NSLog(@"下载后的保存路径:%@", filePath); //为上面代码块返回的路径194                                               195                                               [self updateProgress:100 totalDataLength:100];196                                           } else {197                                               NSLog(@"下载失败,错误信息:%@", error.localizedDescription);198                                               199                                               [self updateProgress:-1 totalDataLength:-1];200                                           }201                                           202                                           [_hud hide:YES];203                                       }];204     205     //类似 NSURLSessionDownloadDelegate 的方法操作206     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;207     [sessionManager setDownloadTaskDidWriteDataBlock:^ (NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {208         NSLog(@"已经接收到响应数据,数据长度为%lld字节...", totalBytesWritten);209         210         [self updateProgress:totalBytesWritten totalDataLength:totalBytesExpectedToWrite];211     }];212     213     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;214     [sessionManager setDownloadTaskDidFinishDownloadingBlock:^ NSURL*(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {215         NSLog(@"已经接收完所有响应数据,下载后的临时保存路径:%@", location);216         return [self saveURL:nil deleteExistFile:YES];217     }];218     219     [task resume];220 }221 222 @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

 

  相关解决方案