2014-07-05 41 views
35

有什麼辦法可以在Swift中創建一個工作線程?例如,如果有一個主要的功能需要大量的計算,並因此導致主線程延遲幾秒鐘,如果我想移動該功能到一個單獨的線程或不阻塞主線程的線程有沒有辦法用Swift做到這一點?如何在iOS Swift中實現多線程,併發或並行?

我已經瀏覽了Swift的Apple文檔的基本和高級組件,但沒有提及併發或並行性,有誰知道如何去做(如果可能)?

+0

盡力做到這一點的OBJ-C –

+0

[CwlUtils(https://github.com/mattgallagher/CwlUtils/)可能是有用的。 – Raphael

回答

45

或者您可以使用操作隊列了。在斯威夫特3:

let queue = OperationQueue() 

queue.addOperation() { 
    // do something in the background 

    OperationQueue.main.addOperation() { 
     // when done, update your UI and/or model on the main queue 
    } 
} 

要麼這樣,還是GCD,這Andy illustrated,做工精細。

查看蘋果的Concurrency Programming Guide瞭解操作隊列和調度隊列(又名Grand Central Dispatch,GCD)的相對優點。儘管該指南仍然使用Objective-C來說明這些示例,但API和概念在Swift中基本相同(只是使用Swift語法)。 GCD文檔和Xcode中的操作隊列描述了Objective-C和Swift API。


順便說一句,你會注意到在上面的例子以及Andy的GCD演示中,我們都使用了「尾隨閉包」。例如,如果你看定義addOperationWithBlock,被定義爲與一個參數的函數,它是一個「閉合」(其類似於在Objective-C的塊):

func addOperation(_ block: @escaping() -> Swift.Void) 

可能導致你假設你如下調用它:

queue.addOperation({ 
    // do something in the background 
}) 

但是當一個函數的最後一個參數是一個封閉,後封語法允許採取最終關閉參數超出該函數的括號,並移動它後,產生:

queue.addOperation() { 
    // do something in the background 
} 

而且,因爲沒有東西留在括號中,你甚至可以更進一步,並刪除那些空括號:

queue.addOperation { 
    // do something in the background 
} 

希望這說明了如何解釋NSOperationQueue/OperationQueue和/或GCD功能聲明並在代碼中使用它們。

17

您可以使用Grand Central Dispatch(GCD)執行此類任務。

這是一個基本的例子:

let backgroundQueue: dispatch_queue_t = dispatch_queue_create("com.a.identifier", DISPATCH_QUEUE_CONCURRENT) 

// can be called as often as needed 
dispatch_async(backgroundQueue) { 
    // do calculations 
} 

// release queue when you are done with all the work 
dispatch_release(backgroundQueue) 
0

This library讓你描述併發的超級表現手法:

func handleError(_ error) { ... } 

HoneyBee.start(on: DispatchQueue.main) { root in 
    root.setErrorHandler(handleError) 
     .chain(function1) // runs on main queue 
     .setBlockPerformer(DispatchQueue.global()) 
     .chain(function2) // runs on background queue 
     .branch { stem in 
      stem.chain(func3) // runs in parallel with func4 
      + 
      stem.chain(func4) // runs in parallel with func3 
     } 
     .chain(func5) // runs after func3 and func4 have finished 
     .setBlockPerformer(DispatchQueue.main) 
     .chain(updateUIFunc) 
}