在Mac OS X 10.6之前,NSOperation跟GCD是採用不同的運作模式,10.6之後NSOperation就改成運作在GCD之上了,換言之他是比較高階的API,但是同時也保有GCD的效能。使用NSOperation時有以下步驟:
- 繼承自NSOperation
- 覆寫main()
- 在main中建立autorelease pool(自動釋放池)
- 把code放到autorelease pool中
- 針對需求,在外部檢查isCancelled等屬性
至於NSOperation中有以下method:
- start:呼叫該函數來執行該operation,但如果沒有特別指定去哪個queue時將會在main queue執行,要特別注意
- dependency:可以設定兩個operation的相依性來設定先後順序。舉例來說我今天下載了一段音訊,要等下載完成後才能進行裁剪,GCD中的dispatch_barrier_async()有提供類似的功能
- priority:這點是我覺得比較有趣的地方,可針對特定的operation來設定setQueuePriority:,像是NSOperationQueuePriorityVeryLow
- completion block:當operation完成後可以在setCompletionBlock:^{}去做其他事情,好比說存檔等等
另外NSOperationQueue相較於NSOperation就更為簡單,僅需要alloc並init即可,之後可調用以下方法:
- concurrent operations:這點比較複雜,簡單來說一個queue可以有多個thread,而每個operation會分配到一個thread來執行。舉例來說我有一個queue,然後加入2個operations,這樣建立兩個thread對應到每個operation,所以我這個queue就會有兩個thread
- maximum number of concurrent operations:設定每個queue中最多只能有幾個operations來執行
- add operation:增加operation到queue,如果要釋放的用使用release方法
- pending operation:查詢在queue中有哪些operations。只有「待執行」和「正在執行」的operation才會在queue中。這部分可以用NSArray來保存operations,或是使用NSDictionary來查詢相關的operation
- pause(suspend)queue:就是停止queue
- cancel operation:如果說該operation尚未執行,呼叫cancel會把operation從queue中移除;如果是正在執行的operation,就要看該operation會不會去檢查isCancelled
- addOperationWithBlock:如果當你不想要有NSOperation的子類別卻又想要來queue中執行,就可在該方法中的block插入程式碼。這有點像GCD的block。不過要注意的是若要參考block外的物件,就必須傳入weak屬性的物件
最後綜合比較NSOperation和GCD,我覺得GCD比較簡單、直覺,但是可以操作的範圍不大(因為就是函數),可是其他物件可以繼承NSOperation,獲得了使用多線程的能力。所以我想當要操作物件時就用NSOperation,然後某些片段(下載等需求)就可以用GCD來解決。總之在iOS中多線程是個很重要的觀念,有這麼好用的功能就要好好用它啊~~