小文件的下载
NSData直接从URL中加载数据
系统提供了方法, 让很多东西都可以直接转换成二进制数据的类型(可以从URL加载,file加载等等,单一数据,直接写入)
// 从提供URL中下载数据
NSData *data = [NSData dataWithContentsOfURL:
[NSURL URLWithString: @"http://b.hiphotos.baidu.com/zhidao/pic/item/728da9773912b31b31187e8c8418367adab4e11b.jpg"]];
// 数据转换成图片
UIImage *image = [UIImage imageWithData:data ];
self.imageView.image = image;
// 将图片数据,转换成data数据
NSData *data1 = UIImageJPEGRepresentation(image, 0);
// 将data数据,进行保存
[data1 writeToFile:@"/Users/liujiaxin/Desktop/image.jpeg" atomically:YES];
NSURLConnection如果是小文件的话,直接异步请求便能得到相应的数据.
NSURL *url = [NSURL URLWithString:@"http://www.people.com.cn/mediafile/pic/20150811/19/7260132349722664171.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 主队列回调 赋值UI
self.imageView.image = [UIImage imageWithData:data];
}];
NSURLSession
IOS7以后不建议使用NSURLConnection进行网络数据处理. [session更加灵活,将操作封装到任务中,通过对任务的操作能够精确的控制操作]NSURLSession, 相当于处理放在会话层执行 (有点大一统的想法, 因为二维码相关的也需要会话)
NSURLSessionTask
/**
* 步骤
* 1、创建task(任务)【任务分为:downloadTask, dataTask(uploadTask)】
* 2、利用 session 创建 task
* 3、创建 session
* 4、执行task - resume 重新执行
*/
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=520it&pwd=520it" dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession *session = [NSURLSession sharedSession];
// 可以不必创建请求直接用url进行获取,但是只能应用于get请求
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
[task resume];
NSURLSessionDownloadTask
NSURLSession *session = [NSURLSession sharedSession];
/**
* 创建下载任务 (该任务启动后便会自己进行下载,并存储的)
*
* @param NSURL 下载那个url 的任务
*
* @block 中的数据 location下载好的文件放在磁盘的位置(会自己创建一个临时文件夹的临时目录)
* 临时目录存放文件,会不定时的删除, 所以最后将文件转移到Cache中
* 响应头
*/
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSFileManager *mgr = [NSFileManager defaultManager];
// [mgr createFileAtPath:[response.suggestedFilename cacheDir] contents:nil attributes:nil];
// 将文件原存储的的地址 ,转换成新的存储地址, (将沙盒cache地址 用url 进行转换)。
[mgr moveItemAtURL:location toURL:[NSURL fileURLWithPath:[response.suggestedFilename cacheDir]] error:nil];
NSLog(@"%@",[response.suggestedFilename cacheDir]);
}];
[task resume];
大文件下载
NSURLConnection,在网络一章中已经说明,对于文件的下载上传管理都是交由代理来完成的.
NSURLConnection的代理方法有:NSURLConnectionDataDelegate
1.接收到响应式调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
2.接收到数据时调用
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
[会调用多次, 每次接受文件是由限制的. 所以会进行多次调用,我们需要将每次接受到的数据进行拼接]
3.连接失败时调用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
4.接收数据完成时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
在大文件下载之前,我们还需要考虑的是,
1>数据放在应用中,建立一个容器专门存放数据,这样调用虽然方便,但是数据存放在应用中,必定会消耗一定的内存,而且会消耗一定得性能.将读取到的数据,存放在沙盒文件中
2>在沙盒中建立文件,存放数据.(一边下载,一边存放)然后将已经保存的数据进行读取就可以了
第一种方案:
// 建立一个容器数据,用来保存下载后的数据(但由于,数据一致存在于内存,所以非常耗性能)
@property(strong,nonatomic) NSMutableData *data;
- (NSMutableData *)data
{
if (!_data) {
_data = [NSMutableData data];
}
return _data;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString *urlStr = [ @"http://120.25.226.186:32812" stringByAppendingPathComponent: @"resources/videos/minion_01.mp4"];
NSURL *url = [NSURL URLWithString:urlStr];
// 设置请求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 设置URLConnection,并且设置代理
NSURLConnection *urlCon = [NSURLConnection connectionWithRequest:request delegate:self];
}
// 代理方法。开始接受相应的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
{
// 由协议头 取出 接收数据的总长度
self.AllLength = response.expectedContentLength;
}
// 开始接收到数据的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 拼接数据
[self.data appendData:data];
// 取出当前文件下载长度
self.currentLength += data.length;
// 得到控件sliderView的值
self.slideView.value = 1.0 * self.currentLength / self.AllLength;
}
// 失败时调用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s",__func__);
}
// 完成时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 完成时 将拼接数据保存
[self.data writeToFile:[@"minion_01.mp4" cacheDir] atomically:YES];
}
第二种方案:
沙盒建立文件,存放下载数据
- (void)viewDidLoad {
[super viewDidLoad];
NSString *urlStr = [ @"http://120.25.226.186:32812" stringByAppendingPathComponent: @"resources/videos/minion_01.mp4"];
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *urlCon = [NSURLConnection connectionWithRequest:request delegate:self];
}
// 代理方法。开始接受相应的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
{
// 由协议头 取出 接收数据的总长度
self.AllLength = response.expectedContentLength;
// 只有利用manager 才能建立文件
NSFileManager *mgr = [NSFileManager defaultManager];
// 有协议头 得到,接收到文件的名称
NSString *filePath = [response.suggestedFilename cacheDir];
NSLog(@"%@",filePath);
self.filePath = filePath;
[mgr createFileAtPath:filePath contents:NULL attributes:NULL];
}
// 开始接收到数据的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 拼接数据
// [self.data appendData:data];
// 建立文件句柄 --- 主要用于文件数据处理
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.filePath];
// 将后一个数据写在前一个数据的后面
[handle seekToEndOfFile];
// 写数据
[handle writeData:data];
// 取出当前文件下载长度
self.currentLength += data.length;
// 得到控件sliderView的值
self.slideView.value = 1.0 * self.currentLength / self.AllLength;
}
// 失败时调用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s",__func__);
}
// 完成时调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 完成时 将拼接数据保存
// [self.data writeToFile:[@"minion_01.mp4" cacheDir] atomically:YES];
}
第三种情况:当出现网络情况很差,或者出现断网的情况,这样的话,如果下载到99.9%,然后断网,在进行下载的话,是不是很坑呢.....
所以应该我们需要进行断点续传
断点续传的实现.
协议头,我们需要传入这么一个参数Range: 将这么一个参数设置的话, 就想到与告诉服务请,请求的数据的范围从什么地方开始,所以我们如果告诉服务器范围(文件已经下载的大小),就可以了
- (IBAction)btnClick:(UIButton *)sender {
// 1.切换按钮图片
sender.selected = !sender.selected;
// 2.判断是否是继续下载
if (sender.selected) {
// 继续下载
NSLog(@"继续下载");
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 只要设置HTTP请求头的Range属性, 就可以实现从指定位置开始下载
/*
表示头500个字节:Range: bytes=0-499
表示第二个500字节:Range: bytes=500-999
表示最后500个字节:Range: bytes=-500
表示500字节以后的范围:Range: bytes=500-
*/
NSString *range = [NSString stringWithFormat:@"bytes %zd-", self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
self.con = [NSURLConnection connectionWithRequest:request delegate:self];
}else
{
// 暂停
NSLog(@"暂停");
[self.con cancel];
}
}
// 接收到服务器的响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
{
self.totalLength = response.expectedContentLength;
// 先去文件中获取下载进度
// 并不是每次都需要创建文件
// 如果已经下载了一部分, 就继续在上一个文件的后面添加
if (self.currentLength > 0) {
return;
}
// 创建容器
// 创建一个空的文件, 用于保存下载的数据
NSFileManager *manager = [NSFileManager defaultManager];
NSString *path = [response.suggestedFilename cacheDir];
NSLog(@"path = %@", path);
[manager createFileAtPath:path contents:nil attributes:nil];
self.path = path;
}
// 接收到服务器返回的数据
// 会调用一次或多次
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 1.创建一个操作文件的句柄
// NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.path];
// 设置数据写入的位置
// 只要调用这个方法, 每次写入数据都会写入到上一次的后面
[self.handle seekToEndOfFile];
// 2.利用句柄往文件中写入数据
[self.handle writeData:data];
// 3.计算当前接收到得数据的总数
self.currentLength += data.length;
// 计算下载比例
self.progressView.progress = 1.0 * self.currentLength/self.totalLength;
}
// 接收完毕
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self.handle closeFile];
self.handle = nil;
NSLog(@"下载完毕");
}
#pragma mark - lazy
- (NSFileHandle *)handle
{
if (!_handle) {
// 1.创建一个操作文件的句柄
_handle = [NSFileHandle fileHandleForWritingAtPath:self.path];
}
return _handle;
}
第四种方式 : 句柄 (太陌生), 输出数据流进行数据的存储(根据文件创建数据输出流, 数据流,只接受byte数据 )
// 设置按钮的监听
- (IBAction)clickBtn:(UIButton *)sender;
// 创建网络请求连接
@property (strong, nonatomic) NSURLConnection *con;
// 记录接收文件的总大小
@property (assign, nonatomic) NSInteger totalLength;
// 记录接收到的当前文件的大小
@property (assign, nonatomic) NSInteger currentLength;
// 记录文件存储路径
@property (copy, nonatomic) NSString *toPath;
// 设置输出流,用于接收数据
@property (strong, nonatomic) NSOutputStream *stream;
@end
@implementation ViewController
- (IBAction)clickBtn:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) {
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 拼接请求头
NSString *range = [NSString stringWithFormat:@"bytes %zd-", self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
self.con = [NSURLConnection connectionWithRequest:request delegate:self];
}else{
// 暂停连接
[self.con cancel];
}
}
// 接收到响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.totalLength = response.expectedContentLength;
// 如果有数据便不在创建新的文件
if (self.currentLength > 0) {
return;
}
NSFileManager *mgr = [NSFileManager defaultManager];
// suggestFilename:就是取出响应头中 记录接收数据的名字(不是路径哦)
self.toPath = [response.suggestedFilename cacheDir];
NSLog(@"%@",self.toPath);
[mgr createFileAtPath:self.toPath contents:nil attributes:nil];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 数据流的模式,允许拼接。
self.stream = [NSOutputStream outputStreamToFileAtPath:self.toPath append:YES];
// 只有打开数据流,才能进行数据的拼接
[self.stream open];
// 数据流,接收byte数据 长度为:最大接收数据的长度,如果不这么设置的话,接收到的数据是有问题的。
[self.stream write:data.bytes maxLength:data.length];
// 设置数据长度
self.currentLength += data.length;
self.progressView.progress = (float)1.0*self.currentLength / self.totalLength;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"%s",__func__);
// 必须和句柄一样 .关闭
[self.stream close];
}
第四种:NSURLSession
NSURLSessionTask--->普通下载
/**
* 参数1、配置,一般为默认配置
* 参数2、设置代理,谁成为它的代理 遵守协议[代理方法中接受数据]
* 参数3、代理回调信息 到那个队列(线程)[一般为主队列]
* 注意 子协议 继承与父协议, 遵守子协议, 就是遵守父协议
*/
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
// 创建人物,用于下载数据
NSURLSessionTask *task = [session dataTaskWithURL:url];
[task resume];
代理方法对接收到的数据进行处理,遵守的协议是:NSURLSessionDataDelegate
#pragma mark - NSURLSessionDataDelegate
// 接收到响应
/**
* 接收到响应时调用
*
* @param session
* @param dataTask 触发事件的任务
* @param response 响应头
* @param completionHandler 回调(告诉我们如何接收(是否)数据)
* NSURLSessionResponseCancel = 0, 默认情况 为 取消 接收数据
* NSURLSessionResponseAllow = 1, 总是允许接收数据
* NSURLSessionResponseBecomeDownload = 2 成为下载时 才接收数据
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
//告诉系统,我们始终接收数据
completionHandler(NSURLSessionResponseAllow);
// 创建文件,用来接收数据
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *toPath = [response.suggestedFilename cacheDir];
self.toPath = toPath;
NSLog(@"%@",toPath);
[mgr createFileAtPath:toPath contents:nil attributes:nil];
}
// 输出流懒加载
- (NSOutputStream *)stream
{
if (!_stream) {
_stream = [NSOutputStream outputStreamToFileAtPath:self.toPath append:YES];
}
return _stream;
}
// 接收到数据
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
//这里我们直接用数据输出流来接受数据. 为了避免多次创建输出流,我们利用懒加载,对输出流进行处理
// NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:self.toPath append:YES];
//
// self.stream = stream;
// 记住要打开数据流
[self.stream open];
[self.stream write:data.bytes maxLength:data.length];
}
// 接收完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
// 关闭输出流
[self.stream close];
self.stream = nil;
// 接收完成 给空间赋值。
NSData *data = [NSData dataWithContentsOfFile:self.toPath];
UIImage *image = [UIImage imageWithData:data];
self.imageView.image = image;
NSLog(@"%s",__func__);
}
NSURLSessionTask可以实现更为简单的断点下载,苹果为我们提供了两个方法: 1.暂停suspend,2.开始resume
, 但调用suspend时, 任务会被暂停.当调用resume是,任务会从暂停的地方再次下载. 省去了NSURLConnection中请求头记录传入数据的麻烦.
在NSURLSession中提供了专门用于包装下载任务的类NSURLSessionDownloadTask----->普通下载
// 设置session会话,专门用来处理任务的执行
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_16.mp4"];
// 利用会话,创建下载任务
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
// 对于不是block创建的任务,不会立即执行, 要调用resume
[task resume];
代理方法的实现遵守的协议是:NSURLSessionDownloadDelegate----代理方法中会把接收完成的数据,存放在临时文件中, 我们需要将文件调出来,放在我们希望的位置location
#pragma mark - NSURLSessionDownloadDelegate
/**
* 开始写入数据
*
* @param session
* @param downloadTask 当前下载任务
* @param bytesWritten 当前这次写入数据的大小
* @param totalBytesWritten 已经写入数据的大小
* @param totalBytesExpectedToWrite 预计写入数据的总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
self.progressView.progress = (float)1.0*totalBytesWritten / totalBytesExpectedToWrite ;
}
/**
* 恢复和暂停
*
* @param session
* @param downloadTask 当前下载任务
* @param fileOffset 恢复之后又从文件的什么地方开始进行写入
* @param expectedTotalBytes 文件剩余总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"%s",__func__);
}
/**
* 下载完成时
*
* @param session
* @param downloadTask 当前下载任务 (属性中有响应头)
* @param location 下载的位置
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSURLResponse *response = downloadTask.response;
NSString *toPath = [response.suggestedFilename cacheDir];
NSLog(@"%@",toPath);
NSFileManager *mgr = [NSFileManager defaultManager];
// 将保存的临时文件,转移到,指定目录
[mgr moveItemAtURL:location toURL:[NSURL fileURLWithPath:toPath] error:nil];
}
// 完成任务
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%s",__func__);
}
NSURLSessionDownLoadTask--->断点下载的应用
NSURLSessionDownloadTask 为我们提供了新的断点下载的方法: cancelByProducingResumeData:void(^)(NSData *resumeData)
用于取消任务时,保存复原的数据,并记录当重新启动任务时,需要从何处继续加载 ---- 主要是用于暂停时数据的保留
dowmloadTaskWithResumeData:
必须在调用 resume
才能开始任务
恢复下载时调用, 并且重新启动下载任务时 , 下载任务的起点已经发生了变化, 由传入的数据 开始启动任务---用于启动时,设置数据开始下载的起点
对于断点下载的优化------>对于每次启动程序, 我们并不需要重新下载, 只需要在本地沙盒中存储的数据--->继续下载就可以了
- 需要完成的就是, 发送请求的时候, 先读取本地数据, 并计算本地数据的大小, 然后在请求头设置时,加入请求数据开始范围
// 设置会话,并设置会话的代理, 以及回调队列
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_16.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 通过本地文件得到,下载了多少数据。 一旦重新启动任务,会从多少数据开始。 但是一旦重启,数据的响应头 中期望数据长度,将会改变,改变量为已将下好的长度,与总长度只差
self.fileSize = [self fileSizeWith:Name];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.fileSize];
// 设置请求头内容
[request setValue:range forHTTPHeaderField:@"Range"];
// 创建下载
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
self.task = task;
[self.task resume];
2.创建方法,专门用于计算文件内容的大小
// 根据传入的文件名,来计算文件的大小
- (NSInteger)fileSizeWith:(NSString *)str;
{
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *toPath = [str cacheDir];
// 文件中的相关参数
NSDictionary *dict = [mgr attributesOfItemAtPath:toPath error:nil];
return [dict[NSFileSize] integerValue];
}
对于多次启动相同下载任务的优化(懒加载任务)
#define Name @"minion_16.mp4"
@implementation ViewController
- (NSURLSessionDataTask *)task
{
if (!_task) {
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_16.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
self.fileSize = [self fileSizeWith:Name];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.fileSize];
[request setValue:range forHTTPHeaderField:@"Range"];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
self.task = task;
}
return _task;
}
Tools 工具类:
为了能更方便的进行下载内容存储,所以我们给下载文件到沙盒路径提供更为简单的方法, 外界调用最方便的方法.
对NSString添加分类,创建实现方法
// 传入字符串,直接在沙盒Cache中生成路径
- (instancetype)cacheDir
{
NSString *cache = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
return [cache stringByAppendingPathComponent:[self lastPathComponent]];
}
// 传入字符串,直接在沙盒Document中生成路径
- (instancetype)docDir
{
NSString *doc = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES).firstObject;
return [doc stringByAppendingPathComponent:[self lastPathComponent]];
}
// 传入字符串,直接在沙盒Temp中生成路径
- (instancetype)temDir
{
NSString *tem = NSTemporaryDirectory();
return [tem stringByAppendingPathComponent:[self lastPathComponent]];
}
网友评论