dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
#1 楼
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)
。有关更多信息,请参阅Apple文档
评论
如果有人想要更像Swift的语法,我创建了Async,它为Async.background {}这样的语法添加了一些糖
–tobiasdm
2014-09-13 21:50
我在xCode 6.0.1和ios 8中使用您的代码。它给出错误为“ QOS_CLASS_BACKGROUND”返回类,并且类型为UInt32,“ dispatch_get_global_queue”需要第一个参数,因为int会导致类型错误。
– Zaal Patel
14-10-29在12:43
因此,在Xcode 6.1.1中,使用简单的简单“ QOS_CLASS_BACKGROUND”不会引起错误。是固定的吗?
–卢卡斯·古森(Lucas Goossen)
15年1月27日在23:18
@LucasGoossen是的,已修复。我已经相应地更新了帖子。
–tobiasdm
2015年2月9日在22:30
@NikitaPronchik答案不很清楚吗?否则,请随时对其进行编辑。
–tobiasdm
15年3月3日在21:16
#2 楼
Dan Beaulieu在swift5中的回答(从swift 3.0.1开始也有效)。 br />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()
})
}
}
}
}
评论
太神奇了,感谢您如此出色地将其更新为Swift 3.0.1格式!
–戴尔·克利福德
17年2月11日在9:03
我比任何在世的人都使用扩展程序。但是使用扩展与原始扩展完全没有真正的危险!
–法蒂
17-2-26在19:56
@Frouo非常优雅,是否可以在4个异步调用全部完成时添加完成处理程序?我知道它有点题外话。
–eonist
17-2-28在11:16
是的,忘记那个链接。您需要的只是一个调度小组-非常非常简单;不用担心!
–法蒂
17年2月28日在19:55
@DilipJangid不能,除非您在后台关闭中的工作非常非常长(〜=无限)。该方法可以持续有限的时间:后台作业需要执行的时间。因此,一旦您的后台作业执行时间+延迟结束,就会立即调用完成关闭。
–rouo
17年5月30日在10:25
#3 楼
最佳实践是定义可多次访问的可重用功能。可重用功能:
例如
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
})
C。要延迟3秒-请注意使用没有背景参数的完成参数:
backgroundThread(background: {
// Your function here to run in the background
},
completion: {
// A function to run in the foreground when the background thread is complete
})
评论
漂亮的代码段,应该是正确的答案。 @戴尔·克利福德
– LoVo
15年6月22日在9:48
精妙的高级现代Swift-y方法,用于从低级C库访问旧式GCD方法。应该是Swift的标准配置。
– Craig Grummitt
2015年9月1日于20:42
非常好。您能否确认,延迟仅适用于完成块。因此,这意味着A.中的延迟没有影响,并且背景块立即执行而没有延迟。
–ObjectiveTC
2015年9月19日于13:46
您应该可以替换if(background!= nil){background!(); }和background?()一起使用,语法更快一些?
–西蒙·本格森(Simon Bengtsson)
16 Jul 25 '15:25
您能否为Swift 3更新此内容?自动转换器将其转换为DispatchQueue.global(priority:Int(DispatchQoS.QoSClass.userInitiated.rawValue))。async {但这会引发错误,例如无法调用类型为'(qos_class_t)的参数列表的类型为'Int'的初始化程序'。在这里可以找到有效的解决方案(DispatchQueue.global(qos:DispatchQoS.QoSClass.userInitiated).async)。
–Dev-iL
16-10-4在18:21
#4 楼
Swift 3版本Swift 3利用新的
DispatchQueue
类来管理队列和线程。要在后台线程上运行某些内容,请使用:let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
print("Run on background thread")
}
,或者如果您需要两行代码中的某些内容: />
您还可以在本教程中获得有关Swift 3中GDC的一些深入信息。
评论
说过。由于您的答案是最好的,因此我添加了一行代码来显示您如何“完成后回叫”。随时放松或编辑,欢呼
–法蒂
17年2月26日在20:01
#5 楼
在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。异步执行>
评论
线程的最佳教程medium.com/@gabriel_lewis/…
– iOS
19年5月15日在5:17
当您使用.background QoS或.userInitiated时,我没有看到任何更改,但对我来说,它可以与.background一起使用
–user5683940
19年8月23日在12:17
您可能看不到使用.background和.userInitiated QoS之间的区别,因为系统可以覆盖您的设置并将.background QoS提升为.userInitiated。对于在主UI队列中使用的队列,这是幕后优化,以使其与父级的QoS相匹配。您可以使用Thread.current.qualityOfService检查当前线程的QoS。
–卡洛里·尼斯托(Karoly Nyisztor)
11月22日19:22
#6 楼
来自Jameson Quave的教程Swift 2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//All stuff here
})
评论
只是为了澄清,为什么要用它代替公认的答案?这只是一个较旧的API吗?
–警笛声
2015年4月19日的19:00
@Sirens我认为这对于支持
– bperdue
15年4月22日在16:27
我在iOs 8.2中使用它来强制进程。
–μολὼν.λαβέ
2015年5月5日17:51
DISPATCH_QUEUE_PRIORITY_DEFAULT恢复为QOS_CLASS_DEFAULT。因此,我想您可以说这是更高级/可接受的语法。
– PostCodeism
2015年12月10日,0:56
#7 楼
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)
}
}
#8 楼
您必须将要在后台运行的更改与要在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()){//更新某些UI}?
–justColbs
2015年11月7日14:22
这不仅仅适用于Swift 2.3及更低版本吗?
–苏尔兹
16-09-23在4:08
#9 楼
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()
}
}
}
#10 楼
无论如何,好的答案还是,无论如何,我想分享我的面向对象的解决方案。赶快获取最新的5。 br /> 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个步骤: >在任务执行之前在UI线程上调用
beforeTask:()->Void
。在后台线程执行后,在UI线程上调用
backgroundTask: (param:BGParam)->BGResult
之后立即在后台线程上调用afterTask:(param:BGResult)->Void
评论
这对我来说很棒。做得好,为什么不把它放在github上呢?
– 36设计使然
16年7月9日在2:36
#11 楼
由于上面已经回答了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上最小。
#12 楼
螺纹的多用途功能public enum QueueType {
case Main
case Background
case LowPriority
case HighPriority
var queue: DispatchQueue {
switch self {
case .Main:
return DispatchQueue.main
case .Background:
return DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
case .LowPriority:
return DispatchQueue.global(qos: .userInitiated)
case .HighPriority:
return DispatchQueue.global(qos: .userInitiated)
}
}
}
func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
queueType.queue.async(execute: closure)
}
使用方法如下:
performOn(.Background) {
//Code
}
#13 楼
我真的很喜欢Dan Beaulieu的回答,但是它不适用于Swift 2.2,并且我认为我们可以避免那些讨厌的强制拆包!#14 楼
Grand Central Dispatch用于在我们的iOS应用中处理多任务。您可以使用此代码
// Using time interval
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
print("Hello World")
}
// Background thread
queue.sync {
for i in 0..<10 {
print("Hello", i)
}
}
// Main thread
for i in 20..<30 {
print("Hello", i)
}
更多信息请使用此链接:https ://www.programminghub.us/2018/07/integrate-dispatcher-in-swift.html
#15 楼
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
// Conversion into base64 string
self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})
#16 楼
在Swift 4.2中有效。import Foundation
class myThread: Thread
{
override func main() {
while(true) {
print("Running in the Thread");
Thread.sleep(forTimeInterval: 4);
}
}
}
let t = myThread();
t.start();
while(true) {
print("Main Loop");
sleep(5);
}
评论
我希望这不被否决。我一直在网上搜索有关如何在Swift中没有GCD的情况下创建实际线程的示例,很难找到任何东西。 GCD不适合我的用例,我发现这个小例子很有帮助。
–马克斯·哈里斯(Max Harris)
11月25日20:02
评论
您在转换哪一部分时遇到问题?为什么在最后一行的分号前有]?
如果您要说明遇到的困难或需要帮助的地方,将会很有帮助。
如果确实可以帮助您,那么您必须接受正确的答案,也可以帮助其他人找到正确的解决方案。
DispatchQueue.global(qos:.background).async {print(“在后台线程上运行”)DispatchQueue.main.async {print(“我们完成了。”)//仅返回主线程,您可以访问UI: label.text =“完成。” }}