NSUrlSession参考的这篇博客,自己也调试了它的代码:http://www.it165.net/pro/html/201406/15223.html ,对NSUrlSession还不太理解,先记下笔记,随后慢慢消化

AppDelegate.h

//
//  AppDelegate.h
//  NSUrlSession
//
//  Created by City--Online on 15/4/27.
//  Copyright (c) 2015年 CYW. All rights reserved.
//

#import <UIKit/UIKit.h>
typedef void(^MyBlock)();
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (copy, nonatomic) MyBlock backgroundURLSessionCompletionHandler;

@end

AppDelegate.m

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{

    self.backgroundURLSessionCompletionHandler = completionHandler;
}

ViewController.m

//
//  ViewController.m
//  NSUrlSession
//
//  Created by City--Online on 15/4/27.
//  Copyright (c) 2015年 CYW. All rights reserved.
//

#import "ViewController.h"
#import "AppDelegate.h"

@interface ViewController ()<NSURLSessionDelegate>
@property (nonatomic,strong)UIImageView *imageView;
@property (nonatomic,strong)UIProgressView *progressIndicator;

@property (nonatomic,strong)NSURLSession *urlSession;         //  普通会话
//@property (nonatomic,strong)NSURLSession *backgroundSession;  //  后台会话
@property (nonatomic,strong)NSURLSessionDownloadTask *sessionDownloadTask;  //  下载Task
@property (nonatomic,strong)NSURLSessionDownloadTask *resumableTask;        //  恢复下载Task
@property (nonatomic,strong)NSURLSessionDownloadTask *backgroundTask;       //  后台下载Task
@property (nonatomic,strong)NSData *partialData;   //  下载的局部数据

@end

@implementation ViewController

- (void)viewDidLoad{

    [super viewDidLoad];

    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 64, 320, 300)];
    [self.view addSubview:_imageView];

    self.progressIndicator = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    _progressIndicator.frame = CGRectMake(50, 500, 220, 50);
    [self.view addSubview:_progressIndicator];

    UIButton *cancleButton = [UIButton buttonWithType:UIButtonTypeSystem];
    cancleButton.frame = CGRectMake(120, 400, 40, 40);
    [cancleButton setTitle:@"取消" forState:UIControlStateNormal];
    [cancleButton addTarget:self action:@selector(didClickCancleButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:cancleButton];

    UIButton *downloadButton = [UIButton buttonWithType:UIButtonTypeSystem];
    downloadButton.frame = CGRectMake(20, 400, 40, 40);
    [downloadButton setTitle:@"下载" forState:UIControlStateNormal];
    [downloadButton addTarget:self action:@selector(didClickDownloadButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:downloadButton];

    UIButton *uploadButton = [UIButton buttonWithType:UIButtonTypeSystem];
    uploadButton.frame = CGRectMake(70, 400, 40, 40);
    [uploadButton setTitle:@"上传" forState:UIControlStateNormal];
    [uploadButton addTarget:self action:@selector(didClickUploadButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:uploadButton];

    UIButton *resumableButton = [UIButton buttonWithType:UIButtonTypeSystem];
    resumableButton.frame = CGRectMake(180, 400, 40, 40);
    [resumableButton setTitle:@"恢复" forState:UIControlStateNormal];
    [resumableButton addTarget:self action:@selector(didClickResuableButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:resumableButton];

    UIButton *backgroundLoadButton = [UIButton buttonWithType:UIButtonTypeSystem];
    backgroundLoadButton.frame = CGRectMake(220, 400, 80, 40);
    [backgroundLoadButton setTitle:@"后台下载" forState:UIControlStateNormal];
    [backgroundLoadButton addTarget:self action:@selector(didClickBackgroundButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backgroundLoadButton];

#pragma mark - 如果我们需要利用NSURLSession进行数据传输我们需要:
    /**
     *  创建一个NSURLSessionConfiguration,用于创建NSSession时设置工作模式(3种)
     *  (1)一般模式(default):工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权。
     *  (2)及时模式(ephemeral):不使用缓存的Cache,Cookie,鉴权。
     *  (3)后台模式(background):在后台完成上传下载,创建Configuration对象的时候需要给一个NSString的ID用于追踪完成工作的Session是哪一个
     */
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    /**
     *  @网络设置:参考NSURLConnection中的设置项
     *  两种创建方法(目前不太懂什么区别)
     *  (1)就是根据刚才创建的Configuration创建一个Session,系统默认创建一个新的OperationQueue处理Session的消息
     *  (2)可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其
     *     设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便
     */
    //NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
    self.urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue currentQueue]];
    NSURL *url = [NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    /**
     *  NSURLSessionUploadTask:上传用的Task,传完以后不会再下载返回结果;
     *  NSURLSessionDownloadTask:下载用的Task;
     *  NSURLSessionDataTask:可以上传内容,上传完成后再进行下载。
     */
    self.sessionDownloadTask = [self.urlSession downloadTaskWithRequest:request];

    //  同NSURLConnection一样,有代理方法也就有block方法
    //    [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    //    }];

}

#pragma mark 点击下载
- (void)didClickDownloadButtonAction:(UIButton *)button{

    // 因为任务默认是挂起状态,需要恢复任务(执行任务)
    [_sessionDownloadTask resume];

}

#pragma mark 点击上传
- (void)didClickUploadButtonAction:(UIButton *)button{

    //判断imageView是否有内容
    if (_imageView.image == nil) {

        NSLog(@"image view is empty");
        return;

    }

    // 0. 上传之前在界面上添加指示符
    UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    // 设置位置???
    CGSize size = _imageView.bounds.size;
    indicator.center = CGPointMake(size.width / 2.0, size.height / 2.0);
    [self.imageView addSubview:indicator];
    [indicator startAnimating];

    // 1. URL
    NSURL *url = [NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"];

    // 2. Request -> PUT,request的默认操作是GET
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0f];
    request.HTTPMethod = @"PUT";

    // *** 设置网络请求的身份验证! ***

    // 1> 授权字符串

    NSString *authStr = @"admin:123456";

    // 2> BASE64的编码,避免数据在网络上以明文传输
    // iOS中,仅对NSData类型的数据提供了BASE64的编码支持
    NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
    NSString *encodeStr = [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    NSString *authValue = [NSString stringWithFormat:@"Basic %@", encodeStr];
    [request setValue:authValue forHTTPHeaderField:@"Authorization"];

    // 3. Session
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    // 4. UploadTask
    NSData *imageData = UIImageJPEGRepresentation(_imageView.image, 0.75);
    //  应用block的请求方式
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        // 上传完成后,data参数转换成string就是服务器返回的内容

        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"OK -> %@", str);

        [NSThread sleepForTimeInterval:5.0f];

        dispatch_async(dispatch_get_main_queue(), ^{

            [indicator stopAnimating];
            [indicator removeFromSuperview];

        });

    }];

    // 因为任务默认是挂起状态,需要恢复任务(执行任务)
    [uploadTask resume];
}

#pragma mark 点击取消
//  NSURLConnection一旦发送是没法取消的。但是,我们可以很容易的取消掉一个NSURLSessionTask任务
- (void)didClickCancleButtonAction:(UIButton *)button{

    /**
     *  当取消后,会回调这个URLSession:task:didCompleteWithError:代理方法,通知你去及时更新UI。当取消一个任务后,也
     *  十分可能会再一次回调这个代理方法URLSession:downloadTask:didWriteData:BytesWritten:totalBytesExpectedToWrite:
     *  当然,didComplete 方法肯定是最后一个回调的。
     */
        if (_sessionDownloadTask) {

            //  取消下载请求
            [_sessionDownloadTask cancel];
            _sessionDownloadTask = nil;
        }

    if (!self.sessionDownloadTask) {

        //  停止下载任务,把待恢复的数据保存到一个变量中,方便后面恢复下载使用
        [self.sessionDownloadTask cancelByProducingResumeData:^(NSData *resumeData) {

            self.partialData = resumeData;

            self.sessionDownloadTask = nil;

        }];
    }
}

#pragma mark  恢复下载(断点续传)
- (void)didClickResuableButtonAction:(UIButton *)button{

    if (self.partialData) {

        self.sessionDownloadTask = [self.urlSession downloadTaskWithResumeData:self.partialData];
        self.partialData = nil;

    }else{

        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"]];
        self.resumableTask = [self.urlSession downloadTaskWithRequest:request];

    }

    [self.sessionDownloadTask resume];

}

#pragma mark 后台下载模式
- (void)didClickBackgroundButtonAction:(UIButton *)button{

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"]];
                                                          self.backgroundTask = [[self backgroundSession] downloadTaskWithRequest:request];

                                                          [self.backgroundTask resume];
                                                          }

#pragma mark - NSURLSessionDownloadTaskDelegate
//  下载完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{

  /**
   *******->appDelegete里面的方法
   typedef void(^MyBlock)();
   @property (copy, nonatomic) MyBlock backgroundURLSessionCompletionHandler;
   //  后台请求结束时调用的方法
   - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{

   self.backgroundURLSessionCompletionHandler = completionHandler;
   }

   */
  //  如果是后台NSURLSession,后台请求结束后会调用这个方法,通知你应该更新UI了
  if (session == [self backgroundSession]) {

      self.backgroundTask = nil;
      AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
      if (appDelegate.backgroundURLSessionCompletionHandler) {
          void(^handler)() = appDelegate.backgroundURLSessionCompletionHandler;
          appDelegate.backgroundURLSessionCompletionHandler = nil;
          handler();
      }

  }

  //  这里的缓存处理做的不好,大家按自己的方法处理就行,还有图片的存储以它本身的URL路径为准,这样是不会有重复的
  NSFileManager *fileManager = [NSFileManager defaultManager];
  NSURL *cachesURLPath = [[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
  //  根据URL获取到下载的文件名,拼接成沙盒的存储路径(location是下载的临时文件目录,在tmp文件夹里面)
  NSURL *destinationPath = [cachesURLPath URLByAppendingPathComponent:[location lastPathComponent]];

  NSError *error = nil;
  BOOL success = [fileManager moveItemAtURL:location toURL:destinationPath error:&error];
  [fileManager removeItemAtURL:location error:NULL];

  //  location是下载的临时文件目录,将文件从临时文件夹复制到沙盒
  //    BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error];
  if (success) {

      dispatch_async(dispatch_get_main_queue(), ^{

          UIImage *image = [UIImage imageWithContentsOfFile:[destinationPath path]];
          self.imageView.image = image;
          //  UIImageView会自动裁剪图片适应它的frame,下面这个属性就是展示原图
          self.imageView.contentMode = UIViewContentModeScaleAspectFill;

      });
  }

}

//  不管任务是否成功,在完成后都会回调这个代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{

  //  如果error是nil,则证明下载是成功的,否则就要通过它来查询失败的原因。如果下载了一部分,这个error会包含一个NSData对象,如果后面要恢复任务可以用到
  if (error == nil) {

      dispatch_async(dispatch_get_main_queue(), ^{

          self.progressIndicator.hidden = YES;
      });
  }

}

//  传输进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{

  double currentValue = totalBytesWritten / (double)totalBytesExpectedToWrite;
  dispatch_async(dispatch_get_main_queue(), ^{
      NSLog(@"%f",currentValue);
      self.progressIndicator.hidden = NO;
      self.progressIndicator.progress = currentValue;
  });
}

//  未知
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{

}

#pragma mark - NSURLSession另一个重要的特性:即使当应用不在前台时,你也可以继续传输任务。当然,我们的会话模式也要为后台模式
- (NSURLSession *)backgroundSession{

  //  通过给的后台token,我们只能创建一个后台会话,所以这里使用dispatch once block
  static NSURLSession *backgroundSession = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      NSURLSessionConfiguration *config=[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"];
//      NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"];
      backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

  });

  return backgroundSession;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

网络之NSURLSession的更多相关文章

  1. iOS网络2——NSURLSession使用详解

    原文在此 一.整体介绍 NSURLSession在2013年随着iOS7的发布一起面世,苹果对它的定位是作为NSURLConnection的替代者,然后逐步将NSURLConnection退出历史舞台 ...

  2. iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充

    一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...

  3. iOS 网络请求NSURLSession

    iOS 7 和 Mac OS X 10.9 Mavericks 中一个显著的变化就是对 Foundation URL 加载系统的彻底重构. 现在已经有人在深入苹果的网络层基础架构的地方做研究了,所以我 ...

  4. iOS开发网络篇-NSURLSession介绍

    NSURLSession: 作用: 和NSURLConnection一样 1.负责发送请求,建立客户端和服务器的连接发送数据给服务器 2.并收集来自服务器的响应数据 步骤: 1.创建NSURLSess ...

  5. iOS之网络请求NSURLSession剖析

    2013年的WWDC大会上,苹果推出了NSURLSession,对Foundation URL加载系统进行了彻底的重构,提供了更丰富的API来处理网络请求,如:支持http2.0协议.直接把数据下载到 ...

  6. Cocoa Touch(五):网络请求 NSURLSession/AFNetworking, GCD, NSURLResquest

    NSURLRequest 网络请求的关键的就是NSURLRequest类,它的实例表示了请求报文实体以及请求的缓存策略等等,各种网络框架的最终目标都是把这个对象编译成为请求报文发送出去.下面用一个实例 ...

  7. NSURLSession访问网络数据

    1.NSMutableURLRequest的设置 //创建NSMutableURLRequest对象 NSMutableURLRequest *request = [NSMutableURLReque ...

  8. IOS网络请求之NSURLSession使用

    前言: 无论是Android还是ios都离不开与服务器交互,这就必须用到网络请求,记得在2013年做iOS的时候那时候用的ASIHTTPRequest框架,现在重新捡起iOS的时候ASIHTTPReq ...

  9. NSURLSession 网络库 - 原生系统送给我们的礼物

    大家在进行iOS开发的时候一定会用到网络操作.但由于早期原生的 NSURLConnection 操作起来有很多不便,使得大家更愿意使用第三方库的解决方案,比如鼎鼎大名的 AFNetworking.正是 ...

随机推荐

  1. mantis邮件设置

     1.cd /var/www/html/mantis     删除 config_inc.php  的$g_enable_email_notification    = OFF;    重启httpd ...

  2. [ASE][Daily Scrum]11.11

    各位1111快乐,不知道大家的卡上还剩多少钱啊~~~ TCP server目前遇到一点小瓶颈,不过server的两个人承诺说明天就可以搞定,给他们加油!~! 今天的plan~ View Shilin ...

  3. Web应用安全之点击劫持(CLICKJACKING)与X-FRAME-OPTIONS HEADER

    点击劫持(clickjacking)与X-Frame-Options Header 文/玄魂 目录 前言... 1.1 点击劫持(clickjacking attacks)... 1.2  Frame ...

  4. Maven 集成Tomcat7插件

    Maven已经是Java的项目管理标配,如何在JavaEE开发使用Maven调用Web应用,是很多同学关心的问题.本文将介绍,Maven如何介绍Tomcat插件. Maven Tomcat插件现在主要 ...

  5. SignalR简介

    什么是SignalR? ASP.NET SignalR是ASP.NET开发人员的库,它简化了向应用程序添加实时Web功能的过程.实时Web功能是指服务器代码在连接的客户端可用时立即将内容推送到连接的客 ...

  6. jQuery基础(2)

    一.jQuery的属性操作 jQuery的属性操作分为四部分: html标签属性操作:是对html文档中的标签属性进行读取,设置和移除操作.比如attr().removeAttr(): DOM属性操作 ...

  7. servlet实现商品商场项目

    1.1 1.创建四个包DButils reposiable service servletJPK DButils包中的类jdbcutils.java 用于获取工具类DButils工具类的DataSou ...

  8. Linux - APT包管理

    dpkg与apt dpkg用来安装本地deb格式软件包,但不会解决软件包的依赖关系. APT(Advanced Packaging Tool)是从更新源获取并安装软件包,而且会解决依赖关系, 但不会安 ...

  9. 整理版jq 复习贴子

    1绝对定位(abs)与相对定位(relative) 区别是相对定位参照自己的位置进行移动(当然需要设置top left这些生效)并且原来的位置保留着 偏移后会把 其它的层遮罩住 绝对定位就是的参照位置 ...

  10. 创建python3虚拟环境指令和冻结所安装的包

    mkvirtualenv file_name -p python3 去掉后面的 P 和python3 代表创建python2环境 其中p代表路径的意思 冻结所安装包命令 pip freeze > ...