週六日鼓搗NSURLSession,效率雖然低下,最後仍是有了一點點眉目。昨天和湯老師一塊兒測試,又對它加深了一點理解。趁熱打鐵,先總結一下。數據庫
封裝的類,對外用的方法,我寫的是類方法,因此,在類方法中,就不能調用自己的@property變量了。解決辦法是:將自己的類先定義爲單例,在利用單例將自己的屬性方法調用出來。session
0.準備工做ide
工具類必須先遵照DownloadDelegate,同時創建一個session的屬性方法工具
@property(nonatomic, strong)NSURLSession * downloadSession;
1.單例的構造方法:post
+(DownloadTool *)instance{ //DownloadTool是當前封裝類的名字 static DownloadTool * aInstance = nil; static dispatch_once_t once_token; dispatch_once(&once_token, ^{ aInstance = [[DownloadTool alloc]init]; aInstance.downloadDic = [NSMutableDictionary dictionary]; //這個是自己的一個@property屬性變量,放在這個裏面進行初始化 }); return aInstance; }
單例構造完成,在類方法裏面,咱們就可使用單例來調出屬性變量。測試
2.單一session的構造方法atom
/** * 建立session */ - (NSURLSession *)isDownloadSession{ if (!_downloadSession) { NSString * configurationStr = @"DownloadTool"; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationStr]; NSURLSession * downloadSession = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; _downloadSession = downloadSession; //_downloadSession是前面定義的屬性方法 } return _downloadSession; }
session用configuration來惟一標示,能夠用identifier來惟一標識,和其餘的不一樣的session來區分,若是整個項目的session用的是同一個的話,能夠用shareSession單例。代理設置爲self,Queue,通常設置爲主線程。url
3.開始下載--這個能夠定義類的調用方法裏面,本身定義,同時將URL傳入進來便可spa
if ([[DownloadTool instance]isDownloadSession]) { NSURLSessionDownloadTask * downloadTask = [[DownloadTool instance].downloadSession downloadTaskWithURL:[NSURL URLWithString:url]]; downloadTask.taskDescription = @"downloadTask01"; [downloadTask resume]; }
3.1 先創建一個downloadTask,用惟一的session來啓動,傳入具體的URL。線程
3.2 taskDescription,能夠用來描述下載任務,這個屬性是能夠修改的,與taskIdentifier不一樣,taskIdentifier是由系統返回是,通常用數字來標識,可用性不高,咱們能夠把對下載任務的描述,惟一標識符等,放在taskDescription裏面,到後面代理方法裏面,能夠根據downloadTask.taskDescription將這個值取出來
3.3 resume:啓動下載;必須調用這個方法,纔會啓動下載,不然不會。固然還有其餘的方法,好比暫停、取消。
4.實現代理方法
4.1 下載完成
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ //創建一個文件夾 BOOL isDirectory; NSString * folderPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingString:@"/script"]; BOOL isExistFolderPath = [[NSFileManager defaultManager]fileExistsAtPath:folderPath isDirectory:&isDirectory]; if (!isExistFolderPath) { BOOL createFile = [[NSFileManager defaultManager]createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil]; if (createFile) { NSLog(@"建立文件成功"); }else{ NSLog(@"建立文件失敗"); } } //改變位置 NSString * sourcePath = location.path; NSString * lastComponent = scScript.url.lastPathComponent; NSString * destinationPath = [folderPath stringByAppendingPathComponent:lastComponent]; [[NSFileManager defaultManager]moveItemAtPath:sourcePath toPath:destinationPath error:nil]; //保存到數據庫 [[DownloadStoreManager sharedInstance]insertScript:scScript]; //發送消息 NSDictionary * dic = @{@"script":scScript}; [[NSNotificationCenter defaultCenter]postNotificationName:DownloadNotificationName object:nil userInfo:dic]; NSLog(@"下載成功------"); }
這個是下載完成比較早的一個方法,後面還有一個方法。
在這個方法裏面,會將下載到的文件,暫時放置temp文件裏面,若是咱們不處理,系統稍後會把這個文件給清除掉,因此,在這個裏面,咱們的任務之一,就是把文件移動到目標文件夾裏面去。若是目標文件不存在,咱們要建立一個文件夾。後面,有可能要存入到數據庫裏面,這個依業務來定。最後發送消息:DownloadNotificationName是我定義的消息的名稱,這個能夠依具體狀況而定。
3.2 數據下載完成的第二個方法
//下載完成 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ if (error) { NSDictionary * dic = @{@"error":@"下載失敗"}; [[NSNotificationCenter defaultCenter]postNotificationName:DownloadNotificationName object:nil userInfo:dic]; } }
一開始,我被這個方法名字給誤導了,覺得只有下載失敗的時候纔會調用這個方法,其實不是的,這個是在任務完成,無論是成功或者失敗,都是要調用的一個方法。若是error爲null,則說明下載成功,若是error有值,則下載失敗,經過error這個值來判別。
當前NSURLSession裏面,還有不少其餘的方法,好比下載Data、upload上傳,原理差很少。
今天先總結到這。昨天晚上太晚了,就沒寫總結,今天早上補上。
最近來接觸新事物時,腦殼剛開始時,老是濛濛的,看來得多接受新事物才能調節啊!