2014-07-05 48 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) 
}