如何在swift中使用线程?
dispatchOnMainThread:^{ NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue())); }];
tobiasdm.. 675
很多已经在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") } }
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") }) })
从Swift 1.1开始,如果没有一些修改,Apple不支持上述语法.通过QOS_CLASS_BACKGROUND
实际上没有工作,而是使用Int(QOS_CLASS_BACKGROUND.value)
.
有关更多信息,请参阅Apples文档
由于上面已经回答了OP问题,我只想添加一些速度考虑因素:
我不建议使用.background线程优先级运行任务,尤其是在iPhone X上,其中任务似乎分配在低功耗内核上.
以下是来自计算密集型函数的一些实际数据,这些函数从XML文件读取(带缓冲)并执行数据插值:
设备名称/ .background/.utility/.default/.userInitiated/.userInteractive
iPhone X:18.7s/6.3s/1.8s/1.8s/1.8s
iPhone 7:4.6s/3.1s/3.0s/2.8s/2.6s
iPhone 5s:7.3s/6.1s/4.0s/4.0s/3.8s
请注意,所有设备的数据集都不相同.它是iPhone X上最大的,也是iPhone 5s上最小的.
来自Jameson Quave的教程
斯威夫特2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //All stuff here })
在Swift 4.2和Xcode 10.1中
我们有三种类型的队列:
1.主队列: 主队列是一个串行队列,由系统创建并与应用程序主线程相关联.
2.全局队列: 全局队列是一个并发队列,我们可以根据任务的优先级请求它.
3.自定义队列:可以由用户创建.通过指定服务质量属性(QoS),自定义并发队列始终映射到其中一个全局队列.
DispatchQueue.main//Main thread DispatchQueue.global(qos: .userInitiated)//?High Priority DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated) DispatchQueue.global(qos: .background)//Lowest Priority DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low) DispatchQueue.global(qos: .utility)//Low Priority DispatchQueue.global(qos: .unspecified)//Absence of Quality
这些所有队列都可以通过两种方式执行
1.同步执行
2.异步执行
DispatchQueue.global(qos: .background).async { // do your job here DispatchQueue.main.async { // update ui here } } //Perform some task and update UI immediately. DispatchQueue.global(qos: .userInitiated).async { // Perform task DispatchQueue.main.async { // Update UI self.tableView.reloadData() } } //To call or execute function after some time DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { //Here call your function } //If you want to do changes in UI use this DispatchQueue.main.async(execute: { //Update UI self.tableView.reloadData() })
来自AppCoda:https://www.appcoda.com/grand-central-dispatch/
//This will print synchronously means, it will print 1-9 & 100-109 func simpleQueues() { let queue = DispatchQueue(label: "com.appcoda.myqueue") queue.sync { for i in 0..<10 { print("", i) } } for i in 100..<110 { print("??", i) } } //This will print asynchronously func simpleQueues() { let queue = DispatchQueue(label: "com.appcoda.myqueue") queue.async { for i in 0..<10 { print("", i) } } for i in 100..<110 { print("??", i) } }
但是很好的答案,无论如何我想分享我的面向对象的解决方案更新为swift 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种通用类型:
BGParam
- 执行时发送给任务的参数类型.
BGResult
- 背景计算结果的类型.
当您创建AsyncTask时,您可以将这些类型传递到后台任务所需的任何类型,但如果您不需要这些类型,则可以将其标记为未使用,只需将其设置为:Void
或者使用较短的语法:()
执行异步任务时,它将执行3个步骤:
beforeTask:()->Void
在执行任务之前在UI线程上调用.
backgroundTask: (param:BGParam)->BGResult
紧接着在后台线程上调用
afterTask:(param:BGResult)->Void
在UI线程上调用后台任务的结果
Dan Beaulieu在swift3中的回答.
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利用新DispatchQueue
类来管理队列和线程.要在后台线程上运行某些东西,您将使用:
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的一些深入信息.
很多已经在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") } }
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") }) })
从Swift 1.1开始,如果没有一些修改,Apple不支持上述语法.通过QOS_CLASS_BACKGROUND
实际上没有工作,而是使用Int(QOS_CLASS_BACKGROUND.value)
.
有关更多信息,请参阅Apples文档
最佳实践是定义可以多次访问的可重用函数.
例如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)) { background?() let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(popTime, dispatch_get_main_queue()) { completion?() } } }
注:雨燕2.0,更换QOS_CLASS_USER_INITIATED.value以上QOS_CLASS_USER_INITIATED.rawValue代替
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秒 - 注意使用没有背景参数的完成参数:
backgroundThread(3.0, completion: { // Your delayed function here to be run in the foreground })
您必须从要在UI上运行的更新中分离出要在后台运行的更改:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { // do your task dispatch_async(dispatch_get_main_queue()) { // update some UI } }
Swift 4.x
把它放在一些文件中:
func background(work: @escaping () -> ()) { DispatchQueue.global(qos: .userInitiated).async { work() } } func main(work: @escaping () -> ()) { DispatchQueue.main.async { work() } }
然后在需要的地方拨打电话:
background { //background job main { //update UI (or what you need to do in main thread) } }