學習GCD歷程

weixin_33716557發表於2015-10-11

遇到xib的知識


NSBundle

  • (文件原話)Many of the methods you use to load resources from a bundle automatically locate the appropriate starting directory and look for resources in known places
  • (blog摘抄)bundle是一個目錄,其中包含了程式會使用到的資源.這些資源包含了如影像,聲音,編譯好的程式碼,nib檔案(使用者也會把bundle稱為plug-in).對應bundle,cocoa提供了類NSBundle.

結合蘋果的開發文件和別人blog,模糊地理解為bundle能提供一個方式(就是獲取檔案路徑
)讓我們從bundel裡面讀取我們需要的東西。文件列舉了3中project型別
Application, Framework, plug-ins。這裡我們會用除了這三個外的在程式上讀取nib檔案或者圖片。

      //讀取nib檔案的方法
      -(NSArray *)loadNibNamed:(NSString *)*name*     
                             owner:(id)*owner*                  
                             options:(NSDictionary *)*options*

返回一個nib裡面所有view的陣列。

注意:
1· 這個陣列不包含Files owner或者代理物件。

引用的blog

總結:

  • 這裡引用的blog我都嘗試跟著做了一遍,稍微有些名目。平時開發時常喜歡按著control鍵拉線,outlet翻譯就是出口的意思,我感覺就是在xib的fileown關聯檔案之後,如果需要顯示xib上的view時候,就需要使用outlet。如果不使用這個,就需要使用以上NSbundle的方法去引用xib檔案的內容
  • 其實無論是使用bundle的方法還是在xib引用file`s owner,最主要就是知道file·s owner是誰,這樣就可以在該檔案使用bundle方法引用xib內容,或者使用outlet。 對了 這裡說的拉線,是關於.h檔案和xib檔案,也就是定義一個IBOutlet與xib關聯。並不是說使用bundle就不用再xib裡面對files owner和view關聯!!

xib還可以動態橋接,這些以後有空補回來!


這裡是GCD初入門學習


這篇東西好久沒寫了,上次有心思寫部落格的時候是過年左右吧,並不是應付面試學習,當是看的是GCD深入理解,裡面的東西確實很多,而且越看越發現自己需要補的知識就越多,到了最後都忘記自己是在學iOS執行緒這東西了。如果看的也覺得忒多的話,我這裡給兩個比較簡單明瞭,而且結合起來能有不錯理解的blog。
(1)關於多執行緒你看我就夠了
(2)死鎖的五個案例
第一個blog裡面關於死鎖的原因沒解釋的很清楚,因此我自己又找了一個blog,後面的解釋的很清楚,還看不懂我也沒辦法了。

Pthreads

一般我們這些初級的,還用不到這麼底層的東西,所以直接跳過,有興趣的可以在作業系統的內容裡面看到。

NSThread

在我的說法裡就是需要自己管理執行緒的整個生命週期,這個肯定能說有好有壞,一般好的就是說自己管理效率上或者自定義方面比較好嘛,不好的肯定就是相對於封裝好的使用比較麻煩嘛。但是這東西我們很多時候也會用例如 [NSThread currentThread];
具體的使用方法,以及有什麼方法呼叫,我也不貼了,自己進去檔案裡面看更加詳細。

NSOperation和NSOperationQueue

GCD

終於到了重點了。Grand Central Dispatch。蘋果為多核處理器提出並行運算提出來的方案,其實也就是為了讓多核能更好的使用罷了。因為一個系統需要同時執行的程式估計會很多吧,多了一個,但其實遠遠還不夠,而且還要考慮作業排程的問題。。。下面科普一些術語。

序列&併發
這些術語描述當任務相對於其它任務被執行,任務序列執行就是每次只有一個任務被執行,任務併發執行就是在同一時間可以有多個任務被執行。

同步&非同步
一個同步函式只在完成了它預定的任務後才返回。
一個非同步函式,剛好相反,會立即返回,預定的任務會完成但不會等它完成。因此,一個非同步函式不會阻塞當前執行緒去執行下一個函式。

臨界區
就是一段程式碼不能被併發執行,也就是,兩個執行緒不能同時執行這段程式碼。

死鎖
兩個(有時更多)東西——在大多數情況下,是執行緒——所謂的死鎖是指它們都卡住了,並等待對方完成或執行其它操作。第一個不能完成是因為它在等待第二個的完成。但第二個也不能完成,因為它在等待第一個的完成。

上下文切換
一個上下文切換指當你在單個程式裡切換執行不同的執行緒時儲存與恢復執行狀態的過程。

執行緒安全
執行緒安全的程式碼能在多執行緒或併發任務中被安全的呼叫,而不會導致任何問題(資料損壞,崩潰,等)。執行緒不安全的程式碼在某個時刻只能在一個上下文中執行。一個執行緒安全程式碼的例子是 NSDictionary 。你可以在同一時間在多個執行緒中使用它而不會有問題。另一方面,NSMutableDictionary 就不是執行緒安全的,應該保證一次只能有一個執行緒訪問它。

併發並行Concurrency vs Parallelism
併發: 一個很短的時間間隔內同時發生兩個執行緒
並行:同時執行兩個執行緒

1010727-9f6d65c86e683e7f.png
併發並行.png

建立佇列
//獲取主執行緒

      dispatch_queue_t queue = dispatch_get_main_queue();
  • 主佇列:這是一個特殊的 序列佇列。什麼是主佇列,大家都知道吧,它用於重新整理 UI,任何需要重新整理 UI 的工作都要在主佇列執行,所以一般耗時的任務都要放到別的執行緒執行。

//一般的寫法

dispatch_queue_t queue= dispatch_queue_create("tk.bourne.testQueue", NULL);      
  • 自己建立的佇列:凡是自己建立的佇列都是 序列佇列。其中第一個引數是識別符號,用於 DEBUG 的時候標識唯一的佇列,可以為空。大家可以看xcode的文件檢視引數意義。
    更新:自己可以建立 序列佇列, 也可以建立 並行佇列。看下面的程式碼(程式碼已更新),它有兩個引數,第一個上面已經說了,第二個才是最重要的。
    第二個引數用來表示建立的佇列是序列的還是並行的,傳入 DISPATCH_QUEUE_SERIAL 或 NULL 表示建立序列佇列。傳入 DISPATCH_QUEUE_CONCURRENT 表示建立並行佇列。

  • 全域性並行佇列:這應該是唯一一個並行佇列,只要是並行任務一般都加入到這個佇列。
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

建立任務

  • 同步任務:不會另開執行緒 (SYNC)
    dispatch_sync(, ^{
    //code here
    NSLog(@"%@", [NSThread currentThread]);
    });

  • 非同步任務:會另開執行緒 (ASYNC)
    dispatch_async(, ^{
    //code here
    NSLog(@"%@", [NSThread currentThread]);
    });

示例:

  NSLog("之前 - %@", NSThread.currentThread())
  dispatch_sync(dispatch_get_main_queue(), { 
  NSLog("sync - %@", NSThread.currentThread())
  })
  NSLog("之後 - %@", NSThread.currentThread())

這裡只會輸出“之前” ,因為後兩個輸出都被阻塞,原因是為什麼呢?
當前使用主執行緒執行UI以及輸出“sync”這段,但是這兩個任務放在了當前的主執行緒佇列---front- 重新整理UI---輸出“sync”--rear
但是因為重新整理UI需要等輸出“sync”完成了才能繼續,但是序列執行任務的原因輸出“sync”又把當前執行緒阻塞了,所以重新整理UI也不能執行了。

對列組
佇列組可以將很多佇列新增到一個組裡,這樣做的好處是,當這個組裡所有的任務都執行完了,佇列組會通過一個方法通知我們。下面是使用方法,這是一個很實用的功能。

    //1.建立佇列組
    dispatch_group_t group = dispatch_group_create();
    //2.建立佇列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //3.多次使用佇列組的方法執行任務, 只有非同步方法
    //3.1.執行3次迴圈
    dispatch_group_async(group, queue, ^{
for (NSInteger i = 0; i < 3; i++) {
    NSLog(@"group-01 - %@", [NSThread currentThread]);
}
    });
    //3.2.主佇列執行8次迴圈
    dispatch_group_async(group, dispatch_get_main_queue(), ^{
for (NSInteger i = 0; i < 8; i++) {
    NSLog(@"group-02 - %@", [NSThread currentThread]);
}
    });
    //3.3.執行5次迴圈
    dispatch_group_async(group, queue, ^{
for (NSInteger i = 0; i < 5; i++) {
    NSLog(@"group-03 - %@", [NSThread currentThread]);
}
    });
    //4.都完成後會自動通知
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"完成 - %@", [NSThread currentThread]);
    });

執行緒同步

  • 互斥鎖 :給需要同步的程式碼塊加一個互斥鎖,就可以保證每次只有一個執行緒訪問此程式碼塊。
    @synchronized(self) {
    //需要執行的程式碼塊
    }

延時執行

  • perform
    // 3秒後自動呼叫self的run:方法,並且傳遞引數:@"abc"
    [self performSelector:@selector(run:) withObject:@"abc" afterDelay:3];

  • GCD 可以使用 GCD 中的 dispatch_after 方法
    // 建立佇列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 設定延時,單位秒
    double delay = 3;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{
    // 3秒後需要執行的任務
    });

  • NSTimer
    NSTimer 是iOS中的一個計時器類,除了延遲執行還有很多用法,不過這裡直說延遲執行的用法
    [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run:) userInfo:@"abc" repeats:NO];

單例模式

  @interface Tool : NSObject
  + (instancetype)sharedTool;
  @end
  @implementation Tool
  static id _instance;
  + (instancetype)sharedTool { 
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _instance = [[Tool alloc] init];
      });
      return _instance;
  }
  @end

從其他執行緒回到主執行緒的方法

我們都知道在其他執行緒操作完成後必須到主執行緒更新UI。所以,介紹完所有的多執行緒方案後,我們來看看有哪些方法可以回到主執行緒。

  • NSThread
    //Objective-C
    [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];
  • GCD
    //Objective-C
    dispatch_async(dispatch_get_main_queue(), ^{
    });

相關文章