GCD6: 在GCD上异步执行非UI相关任务
要在分派隊列上執(zhí)行異步任務,你必須使用下面這些函數(shù)中的其中一個:
dispatch_async為了異步執(zhí)行向分派隊列提交一個 Block Object(2 項都通過參數(shù)指定)
dispatch_async_f為了異步執(zhí)行向分派隊列提交一個 C 函數(shù)和一個上下文引用(3 項通過參數(shù)參數(shù)指定)?
dispatch_async 和dispatch_sync的區(qū)別
dispatch_sync(),同步添加操作。他是等待添加進隊列里面的操作完成之后再繼續(xù)執(zhí)行。
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);NSLog(@"1");dispatch_sync(concurrentQueue, ^(){NSLog(@"2");[NSThread sleepForTimeInterval:10];NSLog(@"3");});NSLog(@"4"); 輸出 : 11:36:25.313 GCDSeTest[544:303] 1 11:36:25.313 GCDSeTest[544:303] 2 11:36:30.313 GCDSeTest[544:303] 3//模擬長時間操作 11:36:30.314 GCDSeTest[544:303] 4dispatch_async ,異步添加進任務隊列,它不會做任何等待
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);NSLog(@"1");dispatch_async(concurrentQueue, ^(){NSLog(@"2");[NSThread sleepForTimeInterval:5];NSLog(@"3");});NSLog(@"4"); 輸出:11:42:43.820 GCDSeTest[568:303] 111:42:43.820 GCDSeTest[568:303] 411:42:43.820 GCDSeTest[568:1003] 211:42:48.821 GCDSeTest[568:1003] 3//模擬長時間操作時間實例:
寫一個 iOS APP, 它能從網(wǎng)絡的 URL 上下載一個圖片。下載完 成之后,APP 應該將圖片展示給用戶。??
1、我們在并發(fā)隊列上異步的啟動一個 block object。2、在這個 block 中我們使用 dispatch_sync 函數(shù)來啟動另一個 Block Object,以從 URL 上下載圖片。我這樣做的目的是想讓并發(fā)隊列中剩余的代碼能夠等到圖片下載完成之后在繼續(xù)執(zhí)行。從一個異步代碼塊上同步下載一個 URL 可以保持這個隊列運行同步函數(shù),而不是主線程。當我們從主線程角度來看的話整個運作仍是異步的。我們關心的問題是在下載圖片的過程中沒有阻塞主線程。
3、圖片下載完畢后,為了在 UI 上將圖片展示給用戶,我們會在主線程上同步執(zhí)行一個?Block?
?
我們計劃的框架: dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async(concurrentQueue, ^{ __block UIImage *image = nil; dispatch_sync(concurrentQueue, ^{ /* Download the image here */ }); dispatch_sync(dispatch_get_main_queue(), ^{ /* Show the image to the user here on the main queue*/ }); });
詳細代碼為:
- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async(concurrentQueue, ^{__block UIImage *image = nil;dispatch_sync(concurrentQueue, ^{//開始下載圖片NSString *urlString = @"http://a.hiphotos.baidu.com/image/pic/item/eac4b74543a9822677de5a5c8982b9014a90ebaa.jpg";NSURL *url = [NSURL URLWithString:urlString];NSURLRequest *request = [NSURLRequest requestWithURL:url];NSError *downloadError = nil;NSData *imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&downloadError];if (downloadError == nil && imageData != nil) {image = [UIImage imageWithData:imageData];//獲得了圖片 }else if (downloadError != nil){NSLog(@"Error happended : %@",downloadError);}else{NSLog(@"No data could get downloaded from the URL");}});dispatch_sync(dispatch_get_main_queue(), ^{//主線程上展示圖片if (image != nil) {UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];[imageView setImage:image];[imageView setContentMode:UIViewContentModeScaleAspectFit];[self.view addSubview:imageView];}else{NSLog(@"Image isn't downloaded. Nothing to display.");}});}); }下面我們來看另一個例子:
假設我們在磁盤的一個文件內存儲了 1000 個隨機數(shù)字的數(shù)組,我們想把這個數(shù)組加載到內存,讓數(shù)字按照升序排列然后展示給用戶。 如果我們沒有數(shù)組,那為什么我們不先創(chuàng)建一個數(shù)組然后再進行加載,最后展示出來呢???下面兩個方法幫助我們在設備上找某文件
- (NSString *)fileLocation{//獲得文件夾位置NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);//見詳解1if ([folders count] == 0) {return nil;}//找到了NSString *documentsFolder = [folders objectAtIndex:0];//返回文件目錄 .../list.txtreturn [documentsFolder stringByAppendingPathComponent:@"list.txt"]; } - (BOOL) hasFileAlreadyBeenCreated{BOOL result = NO;NSFileManager *fileManager = [[NSFileManager alloc]init];//判斷.../list.txt文件是否已經創(chuàng)建if ([fileManager fileExistsAtPath:[self fileLocation]]) {return YES;}return result; }如果沒有我們自己創(chuàng)建一個數(shù)組并存入磁盤,然后再從磁盤讀出該數(shù)組,對該數(shù)組里的數(shù)進行排序顯示:
- (void)fixNumbers{dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async(concurrentQueue, ^{NSUInteger numberOfValuesRequired = 1000;if ([self hasFileAlreadyBeenCreated] == NO) {//如果沒有這1000個隨機數(shù)的數(shù)組,我們創(chuàng)建一個dispatch_sync(concurrentQueue, ^{NSMutableArray *arrayOfRandomNumbers = [[NSMutableArray alloc]initWithCapacity:numberOfValuesRequired];for (NSUInteger counter = 0; counter < numberOfValuesRequired; counter++) {//unsigned int randomNumber = arc4random()%((unsigned int)RAND_MAX + 1);unsigned int randomNumber = arc4random()%1000;[arrayOfRandomNumbers addObject:[NSNumber numberWithUnsignedInt:randomNumber]];}//然后將這個數(shù)組存入磁盤/*BOOL isWrite = [arrayOfRandomNumbers writeToFile:[self fileLocation] atomically:YES];NSLog(@"%d",isWrite);這句代碼打印出的是0 沒有寫入磁盤. 應該是因為arrayOfRandomNumbers是可變數(shù)組不能夠寫入. 要將它轉成NSArray*/NSArray *writeArray = [NSArray arrayWithArray:arrayOfRandomNumbers];BOOL isWrite = [writeArray writeToFile:[self fileLocation] atomically:YES];NSLog(@"%d",isWrite);});}__block NSMutableArray *randomNumbers = nil;//在磁盤中讀取這些數(shù)并且排序dispatch_sync(concurrentQueue, ^{if ([self hasFileAlreadyBeenCreated]) {//讀取randomNumbers = [[NSMutableArray alloc]initWithContentsOfFile:[self fileLocation]];NSLog(@"%@",[self fileLocation]);//排序[randomNumbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {NSNumber *number1 = (NSNumber *)obj1;NSNumber *number2 = (NSNumber *)obj2;return [number1 compare:number2];}];}});dispatch_async(dispatch_get_main_queue(), ^{if ([randomNumbers count] > 0) {for (int i = 0; i < randomNumbers.count; i++) {NSLog(@"%d",[(NSNumber *)[randomNumbers objectAtIndex:i] unsignedIntValue]);}}});}); }?
詳解1:?
iOS中NSSearchPathForDirectoriesInDomains()方法的學習:
FOUNDATION_EXPORT NSArray *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
?第一個參數(shù)NSSearchPathDirectory directory 在iOS中常用NSDocumentDirectory ,?NSDocumentationDirectory ?,NSDownloadsDirectory這三個參數(shù).下面是測試結果
NSDocumentDirectory
-(NSString *) dataFilePath { NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);NSString *documentsDirectory=[paths objectAtIndex:0];return [documentsDirectory stringByAppendingPathComponent:@"data.plist"];}return value:
path:/Users/admin/Library/Application Support/iPhone Simulator/5.0/Applications/4BC5DA66-B3CA-4056-927B-999BC4DBF3CE/Documents/data.plist
NSDocumentationDirectory
-(NSString *) dataFilePath {NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory , NSUserDomainMask, YES); NSString *documentsDirectory=[paths objectAtIndex:0];return [documentsDirectory stringByAppendingPathComponent:@"data.plist" ];}return value: path:/Users/admin/Library/Application Support/iPhone Simulator/5.0/Applications/4BC5DA66-B3CA-4056-927B-999BC4DBF3CE/Library/Documentation/data.plist
NSDownloadsDirectory
-(NSString *) dataFilePath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES); NSString *documentsDirectory=[paths objectAtIndex:0]; return [documentsDirectory stringByAppendingPathComponent:@"data.plist" ];}return value:
path:/Users/admin/Library/Application Support/iPhone Simulator/5.0/Applications/4BC5DA66-B3CA-4056-927B-999BC4DBF3CE/Downloads/data.plist ?
總結:
因為應用是在沙箱(sandbox)中的,在文件讀寫權限上受到限制,只能在幾個目錄下讀寫文件:
- Documents:應用中用戶數(shù)據(jù)可以放在這里,iTunes備份和恢復的時候會包括此目錄
- tmp:存放臨時文件,iTunes不會備份和恢復此目錄,此目錄下文件可能會在應用退出后刪除
- Library/Caches:存放緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出刪除
?
轉載于:https://www.cnblogs.com/safiri/p/4075992.html
總結
以上是生活随笔為你收集整理的GCD6: 在GCD上异步执行非UI相关任务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle用户system解锁
- 下一篇: ContentProvider与Cont