如何在Swift中使用多线程?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
如何在Swift中使用多线程?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
Swift 3.0进行了很多改进。在后台队列上运行某些内容,可以像这样实现:
DispatchQueue.global(qos: .userInitiated).async {
print("This is run on a background queue")
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
}
let qualityOfServiceClass = QOS_CLASS_USER_INITIATED
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
print("This is run on a 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中,没有进行一些修改的情况下,苹果不支持上述语法。传递QOS_CLASS_USER_INITIATED
实际上不起作用,而是使用Int(QOS_CLASS_USER_INITIATED.value)
。
更多信息请参见苹果文档
.background
QoS类。通常.userInitiated
才是您真正需要的。 - Balázs Vincze.userInitiated
,因为它似乎是更明智的默认选项。 - tobiasdmDan Beaulieu在Swift5中给出的答案(自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
})
最佳实践是定义一个可重复使用的函数,可以多次访问。
例如,在全局函数中的类似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?()
}
}
}
注意:在Swift 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
})
background?()
替换if(background != nil){ background!(); }
以获得更简洁的语法? - Simon BengtssonDispatchQueue.global(priority: Int(DispatchQoS.QoSClass.userInitiated.rawValue)).async {
但是这会抛出一个错误,如cannot invoke initializer for type 'Int' with an argument list of type '(qos_class_t)'
。可以在这里找到一个可行的解决方案(DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async
)。 - Dev-iL在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)
}
}
.background
QoS或.userInitiated
时,我没有看到任何更改,但对我来说,使用.background
是有效的。 - user5683940Swift 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 2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//All stuff here
})
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)
}
}
Swift 5
为了简便起见,创建一个名为 "DispatchQueue+Extensions.swift" 的文件,并将以下内容复制进去:
import Foundation
typealias Dispatch = DispatchQueue
extension Dispatch {
static func background(_ task: @escaping () -> ()) {
Dispatch.global(qos: .background).async {
task()
}
}
static func main(_ task: @escaping () -> ()) {
Dispatch.main.async {
task()
}
}
}
使用方法:
Dispatch.background {
// do stuff
Dispatch.main {
// update UI
}
}
你必须将想要在后台运行的更改与你想要在UI上运行的更新分开:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do your task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
}
}
dispatch_async(dispatch_get_main_queue()) { // update some UI }
会被调用吗? - justColbsAsyncTask(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
它有两个通用类型:
BGParam
- 在执行任务时发送到任务的参数的类型。
BGResult
- 后台计算结果的类型。
当创建AsyncTask时,可以将这些类型设置为任何您需要传入和传出后台任务的类型。但是,如果您不需要这些类型,您可以将其设置为未使用,仅使用Void
或更短的语法:()
异步任务被执行时,经历三个步骤:
beforeTask: ()->Void
在UI线程上立即在任务执行之前调用。backgroundTask: (param: BGParam)->BGResult
在后台线程上立即调用afterTask: (param: BGResult)->Void
以来自后台任务的结果在UI线程上调用
]
符号? - akashivskyyDispatchQueue.main.async { print("We finished that.") // only back on the main thread, may you access UI: label.text = "Done." }
}` - Anurag Sharma