NSURLSession的类型(断点续传,开始取消。后台运行)

/**  当前会话*/
@property (nonatomic,strong) NSURLSession *currentSession;

/**  后台会话*/
@property (nonatomic,strong) NSURLSession *backgroundSession;

/**  及时会话*/
@property (nonatomic,strong) NSURLSession *ephemeralSession;

/** 可恢复的下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *canResumeTask;

/** 可取消的下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *canCancelTask;

/** 后台下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *backgroundTask;

/** 用于保存可恢复任务的数据*/
@property (nonatomic,strong) NSData *resumeData;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

/** 创建当前的session*/
- (void)createCurrentSession {
    
    // 使用默认的会话配置器
    NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    // 创建会话
    NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];
    self.currentSession = session;
    // 给其一个描述,即标签
    self.currentSession.sessionDescription = @"kCurrentSession";
}
/**取消*/
- (IBAction)cancel:(id)sender {
    // 取消下载(如果任务存在,取消任务,指针设为nil)
    if(self.canCancelTask) {
        [self.canCancelTask cancel];
        self.canCancelTask = nil;
    }
    NSLog(@"取消了下载:%@",nil);
    
}
/**开始*/
- (IBAction)start:(id)sender {
    
    //  创建会话(默认的会话配置器,并且给会话添加描述),设置请求,session分配任务(创建任务),执行任务
    if (self.currentSession == nil) {
        // 如果没有则创建
        [self createCurrentSession];
    }
    NSString *imageUrl = Base_Url;
    // 创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
    // 下载任务
    self.canCancelTask = [self.currentSession downloadTaskWithRequest:request];
    self.imageView.image = nil;
    
    // 执行下载任务
    [self.canCancelTask resume];
}

#pragma mark - 可断点续传的任务
/**恢复*/
- (IBAction)resumeTask:(id)sender {
    NSString *imageUrl = Base_Url;
    // 创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
    
    // 如果可恢复的下载任务为空,创建任务,并且创新连接会话(创建),
    if (self.canResumeTask == nil && self.currentSession == nil) {
        [self createCurrentSession];
    }
    if (self.resumeData) {
        //        从当前已经有的数据基础上开始下载 downloadTaskWithResumeData
        self.canResumeTask = [self.currentSession downloadTaskWithResumeData:self.resumeData];
        
    } else { // 没有已保存的数据
        self.resumeData = [NSData data];
        self.canResumeTask  = [self.currentSession downloadTaskWithRequest:request];
    }
    [self.canResumeTask resume];
}
/**暂停*/
- (IBAction)pauseTask:(id)sender {
    
    NSLog(@"中断下载:%@",nil);
    
    if (self.canResumeTask) { // 如果当前任务存在,保存数据,并且取消任务,
        [self.canResumeTask cancelByProducingResumeData:^(NSData *resumeData) {
            self.resumeData = resumeData;
            self.canResumeTask = nil;
        }];
    }
    
}

#pragma mark - NSURLSessionDownloadDelegate '下载类代理方法'
/**请求数据完成调用*/
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
    
    NSLog(@"%s",__func__);
    
    NSData *data = [NSData dataWithContentsOfURL:location];
    
    // 请求数据完成,回主线程=显示UI
    dispatch_async(dispatch_get_main_queue(), ^{
        
        self.imageView.image = [UIImage imageWithData:data];
    });
}

/**数据写入*/
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    // 每次断点续传 传入的文件数据 数量
    NSLog(@"bytesWritten--%lld",bytesWritten);
    // 已经写入的文件数据大小
    NSLog(@"totalBytesWritten--%lld",totalBytesWritten);
    // 总共期望传入的文件数据大小
    NSLog(@"totalBytesExpectedToWrite--%lld",totalBytesExpectedToWrite);
    
    //    通过这个方法可以获取接收数据的进度 float progress = totalBytesWritten/totalBytesExpectedToWrite;
    
}

// Sent when a download has been resumed. 类似断点续传
// 在恢复下载的时候调用,从fileOffset位置处恢复下载
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes {
    
    // 文件恢复下载的偏移量,即文件中数据的位置
    NSLog(@"fileOffset--%lld",fileOffset);
    
}

#pragma mark - NSURLSession ‘代理方法‘
// 无论成功或者失败 这个方法都会调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    
    NSLog(@"error:%@",error);
}

// 完成了后台下载任务
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    NSLog(@"%s",__func__);
    
    // 得到应用程序代理
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    
    //
    if (self.currentSession == session) {
        // 应用程序用一个block中间变量保存 程序完成的block
        if(appDelegate.backgroundSessioCompletionHandler) {
            
            
            void (^handler)() = appDelegate.backgroundSessioCompletionHandler;
            appDelegate.backgroundSessioCompletionHandler = nil;
            // 应用程序收到
            handler();
        }
    }
    
}

#pragma mark - 后台下载
- (NSURLSession *)backgroundSession {
    
    // 单例形式的后台会话
    static NSURLSession *backgroundSession = nil;
    //这里用GCD一次性代码创建一个后台会话单例,并设置会话描述
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        NSURLSessionConfiguration *bgConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"background"];
        
        // 创建会话 后台会话配置器
        backgroundSession = [NSURLSession sessionWithConfiguration:bgConfig delegate:self delegateQueue:nil];
        backgroundSession.sessionDescription = @"background";
    });
    return backgroundSession;
}

- (IBAction)backgroundTask:(id)sender {
    
    if (self.currentSession == nil) {
        self.currentSession = [self backgroundSession];
    }
    NSString *imageUrl = Base_Url;
    // 创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
    self.backgroundTask = [self.currentSession downloadTaskWithRequest:request];
    
    // 开始执行后台下载任务
    [self.backgroundTask resume];
}
@property (copy,nonatomic) void(^backgroundSessioCompletionHandler)(void);

/**
 *  后台下载完成后,程序被唤醒,该方法被调用
 */
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {

    NSLog(@"%s",__func__);
    self.backgroundSessioCompletionHandler = completionHandler;
    
}


你可能感兴趣的:(iOS网络)