日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GCD6: 在GCD上异步执行非UI相关任务

發布時間:2023/12/2 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GCD6: 在GCD上异步执行非UI相关任务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
討論:在主隊列、串行隊列和并發隊列上異步執行代碼塊才能見識到 GCD 的真正實力。

要在分派隊列上執行異步任務,你必須使用下面這些函數中的其中一個:

dispatch_async為了異步執行向分派隊列提交一個 Block Object(2 項都通過參數指定)

dispatch_async_f為了異步執行向分派隊列提交一個 C 函數和一個上下文引用(3 項通過參數參數指定)?

dispatch_async 和dispatch_sync的區別

dispatch_sync(),同步添加操作。他是等待添加進隊列里面的操作完成之后再繼續執行。

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] 4

dispatch_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, 它能從網絡的 URL 上下載一個圖片。下載完 成之后,APP 應該將圖片展示給用戶。?

?

1、我們在并發隊列上異步的啟動一個 block object。

2、在這個 block 中我們使用 dispatch_sync 函數來啟動另一個 Block Object,以從 URL 上下載圖片。我這樣做的目的是想讓并發隊列中剩余的代碼能夠等到圖片下載完成之后在繼續執行。從一個異步代碼塊上同步下載一個 URL 可以保持這個隊列運行同步函數,而不是主線程。當我們從主線程角度來看的話整個運作仍是異步的。我們關心的問題是在下載圖片的過程中沒有阻塞主線程。

3、圖片下載完畢后,為了在 UI 上將圖片展示給用戶,我們會在主線程上同步執行一個?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 個隨機數字的數組,我們想把這個數組加載到內存,讓數字按照升序排列然后展示給用戶。 如果我們沒有數組,那為什么我們不先創建一個數組然后再進行加載,最后展示出來呢??

?下面兩個方法幫助我們在設備上找某文件

- (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文件是否已經創建if ([fileManager fileExistsAtPath:[self fileLocation]]) {return YES;}return result; }

如果沒有我們自己創建一個數組并存入磁盤,然后再從磁盤讀出該數組,對該數組里的數進行排序顯示:

- (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個隨機數的數組,我們創建一個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]];}//然后將這個數組存入磁盤/*BOOL isWrite = [arrayOfRandomNumbers writeToFile:[self fileLocation] atomically:YES];NSLog(@"%d",isWrite);這句代碼打印出的是0 沒有寫入磁盤. 應該是因為arrayOfRandomNumbers是可變數組不能夠寫入. 要將它轉成NSArray*/NSArray *writeArray = [NSArray arrayWithArray:arrayOfRandomNumbers];BOOL isWrite = [writeArray writeToFile:[self fileLocation] atomically:YES];NSLog(@"%d",isWrite);});}__block NSMutableArray *randomNumbers = nil;//在磁盤中讀取這些數并且排序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);

?第一個參數NSSearchPathDirectory directory 在iOS中常用NSDocumentDirectory ,?NSDocumentationDirectory ?,NSDownloadsDirectory這三個參數.下面是測試結果

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:應用中用戶數據可以放在這里,iTunes備份和恢復的時候會包括此目錄
  • tmp:存放臨時文件,iTunes不會備份和恢復此目錄,此目錄下文件可能會在應用退出后刪除
  • Library/Caches:存放緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出刪除

?


轉載于:https://www.cnblogs.com/safiri/p/4075992.html

總結

以上是生活随笔為你收集整理的GCD6: 在GCD上异步执行非UI相关任务的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。