如何在swift中使用后台线程?
如何在swift中使用线程?
dispatchOnMainThread:^{ NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue())); }];
Swift 3.0+
很多已经在Swift 3.0 现代化 。 在后台线程上运行一些东西看起来像这样:
DispatchQueue.global(qos: .background).async { print("This is run on the background queue") DispatchQueue.main.async { print("This is run on the main queue, after the previous code in outer block") } }
Swift 1.2到2.3
let qualityOfServiceClass = QOS_CLASS_BACKGROUND let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0) dispatch_async(backgroundQueue, { print("This is run on the background queue") dispatch_async(dispatch_get_main_queue(), { () -> Void in print("This is run on the main queue, after the previous code in outer block") }) })
Pre Swift 1.2 – 已知问题
从Swift 1.1开始,Apple没有经过一些修改就不支持上面的语法。 传递QOS_CLASS_BACKGROUND
实际上并不工作,而是使用Int(QOS_CLASS_BACKGROUND.value)
。
欲了解更多信息,请参阅苹果文档
最好的做法是定义一个可以多次访问的可重用函数。
可重复使用的function:
例如像AppDelegate.swift这样的全局函数。
func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) { dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) { if(background != nil){ background!(); } let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(popTime, dispatch_get_main_queue()) { if(completion != nil){ completion!(); } } } }
注意:在Swift 2.0中,用QOS_CLASS_USER_INITIATED.rawValuereplace上面的QOS_CLASS_USER_INITIATED.value
用法:
A.要在后台运行一个进程,延迟3秒:
backgroundThread(3.0, background: { // Your background function here })
B.在后台运行一个进程然后在前台运行一个完成:
backgroundThread(background: { // Your function here to run in the background }, completion: { // A function to run in the foreground when the background thread is complete })
C.延迟3秒钟 – logging使用完成参数,无背景参数:
backgroundThread(3.0, completion: { // Your delayed function here to be run in the foreground })
从Jameson Quave的教程
Swift 2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //All stuff here })
Dan Beaulieu在swift3的回答。
Swift 3.0.1
extension DispatchQueue { static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) { DispatchQueue.global(qos: .background).async { background?() if let completion = completion { DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: { completion() }) } } } }
用法
DispatchQueue.background(delay: 3.0, background: { // do something in background }, completion: { // when background job finishes, wait 3 seconds and do something in main thread }) DispatchQueue.background(background: { // do something in background }, completion:{ // when background job finished, do something in main thread }) DispatchQueue.background(delay: 3.0, completion:{ // do something in main thread after 3 seconds })
Swift 3版本
Swift 3利用新的DispatchQueue
类来pipe理队列和线程。 要在后台线程上运行一些东西,你可以使用:
let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background) backgroundQueue.async { print("Run on background thread") }
或者如果你想要两行代码中的东西:
DispatchQueue.global(qos: .background).async { print("Run on background thread") DispatchQueue.main.async { print("We finished that.") // only back on the main thread, may you access UI: label.text = "Done." } }
在本教程中,您还可以在Swift 3中获得一些有关GDC的深入信息。
您必须从要在UI上运行的更新中分离出想要在后台运行的更改:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { // do your task dispatch_async(dispatch_get_main_queue()) { // update some UI } }
好的答案虽然,无论如何,我想分享我的面向对象的解决scheme更新为迅速3 。
请查看: AsyncTask
从概念上来说,受到了Android的AsyncTask的启发,我在Swift中编写了自己的类
AsyncTask支持正确和简单地使用UI线程。 这个类允许执行后台操作并在UI线程上发布结果。
这里有几个用法示例
例1 –
AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void print(p);//print the value in background thread }).execute("Hello async");//execute with value 'Hello async'
例2 –
let task2=AsyncTask(beforeTask: { print("pre execution");//print 'pre execution' before backgroundTask },backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String if p>0{//check if execution value is bigger than zero return "positive"//pass String "poitive" to afterTask } return "negative";//otherwise pass String "negative" }, afterTask: {(p:String) in print(p);//print background task result }); task2.execute(1);//execute with value 1
它有2个通用types:
-
BGParam
– 执行时发送给任务的参数的types。 -
BGResult
– 背景计算结果的types。当您创build一个AsyncTask时,您可以将这些types转换为任何需要传入和传出后台任务的types,但如果您不需要这些types,则可以将其设置为
Void
:将其设置为Void
或语法较短:(()
在执行asynchronous任务时,需要经过3个步骤:
-
beforeTask:()->Void
在执行任务之前在UI线程上调用beforeTask:()->Void
。 -
backgroundTask: (param:BGParam)->BGResult
在后台线程后立即调用backgroundTask: (param:BGParam)->BGResult
-
afterTask:(param:BGResult)->Void
在UI线程上使用后台任务的结果调用的afterTask:(param:BGResult)->Void
我真的很喜欢Dan Beaulieu的回答,但是它不适用于Swift 2.2,我想我们可以避免那些令人讨厌的强制解开!
func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) { dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { background?() if let completion = completion{ let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(popTime, dispatch_get_main_queue()) { completion() } } } }
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { // Conversion into base64 string self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn) })