iphone ios 如何使用gcd

來源:互聯網
上載者:User

1。GCD之dispatch queue

http://www.cnblogs.com/scorpiozj/archive/2011/07/25/2116459.html

2。iOS中GCD的魔力

http://blog.csdn.net/favormm/article/details/6453260

3。官方 ,內容真的很多

http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

4.詳解IOS開發應用之並發Dispatch Queues

http://mobile.51cto.com/iphone-283323.htm

5。斯坦福大學關於gcd的講義

http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/lectures/Lecture%2013_0.pdf



gcd其實就是牛逼簡化版的多線程。gcd和block是親兄弟,所以學習gcd前需要瞭解block,不知道也沒事,看看代碼就明白了。

函數原型

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);


async表明非同步運行,.(除了async,還有sync,delay,本文以async為例).

queue則是你把任務交給誰來處理了

block代表的是你要做的事情


queue有三種 

  • Main: tasks execute serially on your application’s main thread

  • Concurrent: tasks start executing in FIFO order, but can run concurrently.

  • Serial: tasks execute one at a time in FIFO order

  • (1)serial queues(串列隊列)又稱私人調度隊列(private),一般用再對特定資源的同步訪問上。我們可以根據需要建立任意數量的串列隊列,每一個串列隊列之間是並發的。
  • (2)並行隊列,又稱global dispatch queue。並行隊列雖然可以並發的執行多個任務,但是任務開始執行的順序和其排入佇列的順序相同。我們自己不能去建立並行調度隊列。只有三個可用的global concurrent queues。
  • (3)main dispatch queue 是一個全域可用的串列隊列,其在行用程式的主線程上執行任務。此隊列的任務和應用程式的主迴圈(run loop)要執行的事件來源交替執行。因為其運行在應用程式的主線程,main queue經常用來作為應用程式的一個同步點

    先看一段代碼

    @interface UIImageView (DispatchLoad)  - (void) setImageFromUrl:(NSString*)urlString;  - (void) setImageFromUrl:(NSString*)urlString                 completion:(void (^)(void))completion;  @end  


    #import "UIImageView+DispatchLoad.h"  @implementation UIImageView (DispatchLoad)  - (void) setImageFromUrl:(NSString*)urlString {      [self setImageFromUrl:urlString completion:NULL];  }  - (void) setImageFromUrl:(NSString*)urlString                 completion:(void (^)(void))completion {            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                    NSLog(@"Starting: %@", urlString);          UIImage *avatarImage = nil;           NSURL *url = [NSURL URLWithString:urlString];          NSData *responseData = [NSData dataWithContentsOfURL:url];          avatarImage = [UIImage imageWithData:responseData];          NSLog(@"Finishing: %@", urlString);                    if (avatarImage) {              dispatch_async(dispatch_get_main_queue(), ^{                  self.image = avatarImage;              });              dispatch_async(dispatch_get_main_queue(), completion);          }          else {              NSLog(@"-- impossible download: %@", urlString);          }      });     }  @end  


  • 以上代碼主要是實現,映像非同步載入。分解一下:1>添加到gcd隊列
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  

    這個代碼主要實現,將映像載入block添加到queue隊列中,

    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),

    這個是擷取全域並行隊列(global dispatch queue),系統隊列,只有3個。2>載入映像。這個濾過3>通知或更新主線程

    dispatch_async(dispatch_get_main_queue(), ^{                  self.image = avatarImage;              });              dispatch_async(dispatch_get_main_queue(), completion);  

    “block的一個優勢是可以使用其自己範圍外的變數,例如,一個block可以讀取其父範圍的變數值,此值是copy到了block heap的資料結構中。當block被加入到dispatch queue中,這些值通常為唯讀形式。”

    而更新UI只能在主線程中實現,所以調用主線程函數 completion
    這樣就完成了非同步載入映像的流程。
    當想要任務按照某一個特定的順序執行時,串列隊列是很有用的。串列隊列在同一個時間只執行一個任務。我們可以使用串列隊列代替鎖去保護共用的資料。和鎖不同,一個串列隊列可以保證任務在一個可預知的順序下執行。

    和並發隊列不同,我們要自己去建立和管理串列隊列,可以建立任意數量的串列隊列。當我們建立串列隊列時,應出於某種目的,如保護資源,或者同步應用程式的某些關鍵行為。

    下面的代碼錶述了怎麼建立一個自訂的串列隊列,函數dispath_queue_create需要兩個參數,隊列的名字,隊列的屬性。調試器和效能工具顯示隊列的名字協助我們去跟蹤任務是如何執行,隊列的屬性被保留供將來使用,應該為NULL

       
    1. dispatch_queue_t queue;  
    2. queue = dispatch_queue_create("com.example.MyQueue", NULL); 

    除了自己建立的自訂隊列,系統會自動的給我建立一個串列隊列並和應用程式的主線程綁定到一起。下面講述如何獲得它。

    貼幾段斯坦福大學關於gcd的代碼,這段代碼逐步示範了如何修正錯誤,其中用到的既是串列隊列
    1。這個是原始代碼

    - (void)viewWillAppear:(BOOL)animated{    NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL];    UIImage *image = [UIImage imageWithData:imageData];    self.imageView.image = image;    self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);    self.scrollView.contentSize = image.size;}

    2。這個是採用gcdd的代碼,裡面有錯誤3處

    - (void)viewWillAppear:(BOOL)animated{    dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL);    dispatch_async(downloadQueue, ^{         NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL];         UIImage *image = [UIImage imageWithData:imageData];         self.imageView.image = image;         self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);         self.scrollView.contentSize = image.size;    });}

    3。第一個錯誤,UI更新只能在主線程中 Problem! UIKit calls can only happen in the main thread!改正後如下:

    - (void)viewWillAppear:(BOOL)animated{    dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL);    dispatch_async(downloadQueue, ^{         NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL];         dispatch_async(dispatch_get_main_queue(), ^{             UIImage *image = [UIImage imageWithData:imageData];             self.imageView.image = image;             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);             self.scrollView.contentSize = image.size;         });}); }

    4。第二個錯誤,NSManagedObjectContext並不是安全執行緒的,gcd中訪問成員變數有危險Problem! NSManagedObjectContext is not thread safe,
    so we can’t call photo.URL in downloadQueue’s t
    改正後如下:

    - (void)viewWillAppear:(BOOL)animated{    NSString *url = photo.URL;    dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL);    dispatch_async(downloadQueue, ^{        NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:url];        dispatch_async(dispatch_get_main_queue(), ^{            UIImage *image = [UIImage imageWithData:imageData];            self.imageView.image = image;            self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);            self.scrollView.contentSize = image.size;}); });}

    5。第三個錯誤,隊列建立後沒有釋放,記憶體泄露

    - (void)viewWillAppear:(BOOL)animated{    NSString *url = photo.URL;    dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL);    dispatch_async(downloadQueue, ^{        NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:url];        dispatch_async(dispatch_get_main_queue(), ^{            UIImage *image = [UIImage imageWithData:imageData];            self.imageView.image = image;            self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);            self.scrollView.contentSize = image.size;}); });dispatch_release(downloadQueue); //won’tactuallygoawayuntilqueueisempty }

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.