如何在 Swift 3 中创建调度队列
How to create dispatch queue in Swift 3
在 Swift 2 中,我能够使用以下代码创建队列:
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)
但这不会在 Swift 3 中编译。
在 Swift 3 中写这个的首选方法是什么?
创建并发队列
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {
}
创建串行队列
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync {
}
异步获取主队列
DispatchQueue.main.async {
}
同步获取主队列
DispatchQueue.main.sync {
}
获取后台线程之一
DispatchQueue.global(qos: .background).async {
}
Xcode 8.2 测试版 2:
获取后台线程之一
DispatchQueue.global(qos: .default).async {
}
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
如果您想了解如何使用这些队列。请参阅此 answer
在 >=Swift 3 下编译。这个例子包含了我们需要的大部分语法。
QoS - 新的服务质量语法
weak self
- 破坏保留周期
如果 self 不可用,什么都不做
async global utility queue
- 对于网络查询,不等待结果,它是一个并发队列,块(通常)在启动时不等待。并发队列的例外情况可能是,当先前已达到其任务限制时,队列会暂时变成串行队列并等待该队列中的某个先前任务完成。
async main queue
- 对于触摸 UI,块不等待结果,而是在开始时等待它的槽。主队列是串行队列。
当然,你需要为此添加一些错误检查...
DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in
guard let strongSelf = self else { return }
strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in
if error != nil {
print("error:\(error)")
} else {
DispatchQueue.main.async { () -> Void in
activityIndicator.removeFromSuperview()
strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
}
}
}
}
现在很简单:
let serialQueue = DispatchQueue(label: "my serial queue")
默认是串行的,要获得并发,你可以使用可选属性参数 .concurrent
编译于 XCode 8,Swift 3
https://github.com/rpthomas/Jedisware
@IBAction func tap(_ sender: AnyObject) {
let thisEmail = "emailaddress.com"
let thisPassword = "myPassword"
DispatchQueue.global(qos: .background).async {
// Validate user input
let result = self.validate(thisEmail, password: thisPassword)
// Go back to the main thread to update the UI
DispatchQueue.main.async {
if !result
{
self.displayFailureAlert()
}
}
}
}
您可以在 swift 3.0
中使用此代码创建调度队列
DispatchQueue.main.async
{
/*Write your code here*/
}
/* or */
let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
/*Write your code here*/
}
我这样做了,如果您想刷新 UI 以在用户不注意的情况下显示新数据,这尤其重要,例如 UITableView 或 UIPickerView。
DispatchQueue.main.async
{
/*Write your thread code here*/
}
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version
let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version
我在 Xcode 8 和 Swift 3 中重新编写了您的代码,这些更改与您的 Swift 2 版本形成对比。
DispatchQueue.main.async(execute: {
// write code
})
串行队列:
let serial = DispatchQueue(label: "Queuename")
serial.sync {
//Code Here
}
并发队列:
let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)
concurrent.sync {
//Code Here
}
DispatchQueue.main.async {
self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
}
OperationQueue.main.addOperation {
self.lblGenre.text = self.movGenre
}
//如果您需要在 viewcontroller
上填充对象(标签、图像视图、文本视图),请使用操作队列
DispatchQueue.main.async(execute: {
// code
})
Swift 3
你想在 swift 代码中调用一些闭包然后你想在故事板中更改任何类型的关闭更改属于视图你的应用程序将崩溃
但是你想使用 dispatch 方法你的应用程序不会崩溃
异步方法
DispatchQueue.main.async
{
//Write code here
}
同步方法
DispatchQueue.main.sync
{
//Write code here
}
对于Swift 3
DispatchQueue.main.async {
// Write your code here
}
let newQueue = DispatchQueue(label: "newname")
newQueue.sync {
// your code
}
由于上面已经回答了 OP 问题,我只想添加一些速度注意事项:
您在 DispatchQueue.global.
中分配给异步函数的优先级 class 有很大不同
我不推荐具有 .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 上最小。
更新 swift 5
Serial Queue
let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
// code to execute
}
Concurrent Queue
let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
concurrentQueue.async {
// code to execute
}
参数
标签
附加到队列的字符串标签,用于在仪器、示例、堆栈快照和崩溃报告等调试工具中唯一标识它。因为应用程序、库和框架都可以创建自己的调度队列,所以建议使用反向 DNS 命名样式 (com.example.myqueue)。此参数是可选的,可以为 NULL。
qos
与队列关联的服务质量级别。该值决定了系统调度任务执行的优先级。有关可能值的列表,请参阅 DispatchQoS.QoSClass.
属性
与队列关联的属性。包括 concurrent 属性来创建一个并发执行任务的调度队列。如果省略该属性,调度队列将串行执行任务。
autoreleaseFrequency
自动释放由队列调度的块创建的对象的频率。有关可能值的列表,请参阅 DispatchQueue.AutoreleaseFrequency.
目标
执行块的目标队列。如果您希望系统提供适合当前对象的队列,请指定DISPATCH_TARGET_QUEUE_DEFAULT。
在 Swift 2 中,我能够使用以下代码创建队列:
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)
但这不会在 Swift 3 中编译。
在 Swift 3 中写这个的首选方法是什么?
创建并发队列
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {
}
创建串行队列
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync {
}
异步获取主队列
DispatchQueue.main.async {
}
同步获取主队列
DispatchQueue.main.sync {
}
获取后台线程之一
DispatchQueue.global(qos: .background).async {
}
Xcode 8.2 测试版 2:
获取后台线程之一
DispatchQueue.global(qos: .default).async {
}
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
如果您想了解如何使用这些队列。请参阅此 answer
在 >=Swift 3 下编译。这个例子包含了我们需要的大部分语法。
QoS - 新的服务质量语法
weak self
- 破坏保留周期
如果 self 不可用,什么都不做
async global utility queue
- 对于网络查询,不等待结果,它是一个并发队列,块(通常)在启动时不等待。并发队列的例外情况可能是,当先前已达到其任务限制时,队列会暂时变成串行队列并等待该队列中的某个先前任务完成。
async main queue
- 对于触摸 UI,块不等待结果,而是在开始时等待它的槽。主队列是串行队列。
当然,你需要为此添加一些错误检查...
DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in
guard let strongSelf = self else { return }
strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in
if error != nil {
print("error:\(error)")
} else {
DispatchQueue.main.async { () -> Void in
activityIndicator.removeFromSuperview()
strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
}
}
}
}
现在很简单:
let serialQueue = DispatchQueue(label: "my serial queue")
默认是串行的,要获得并发,你可以使用可选属性参数 .concurrent
编译于 XCode 8,Swift 3 https://github.com/rpthomas/Jedisware
@IBAction func tap(_ sender: AnyObject) {
let thisEmail = "emailaddress.com"
let thisPassword = "myPassword"
DispatchQueue.global(qos: .background).async {
// Validate user input
let result = self.validate(thisEmail, password: thisPassword)
// Go back to the main thread to update the UI
DispatchQueue.main.async {
if !result
{
self.displayFailureAlert()
}
}
}
}
您可以在 swift 3.0
中使用此代码创建调度队列DispatchQueue.main.async
{
/*Write your code here*/
}
/* or */
let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
/*Write your code here*/
}
我这样做了,如果您想刷新 UI 以在用户不注意的情况下显示新数据,这尤其重要,例如 UITableView 或 UIPickerView。
DispatchQueue.main.async
{
/*Write your thread code here*/
}
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version
let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version
我在 Xcode 8 和 Swift 3 中重新编写了您的代码,这些更改与您的 Swift 2 版本形成对比。
DispatchQueue.main.async(execute: {
// write code
})
串行队列:
let serial = DispatchQueue(label: "Queuename")
serial.sync {
//Code Here
}
并发队列:
let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)
concurrent.sync {
//Code Here
}
DispatchQueue.main.async {
self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
}
OperationQueue.main.addOperation {
self.lblGenre.text = self.movGenre
}
//如果您需要在 viewcontroller
上填充对象(标签、图像视图、文本视图),请使用操作队列DispatchQueue.main.async(execute: {
// code
})
Swift 3
你想在 swift 代码中调用一些闭包然后你想在故事板中更改任何类型的关闭更改属于视图你的应用程序将崩溃
但是你想使用 dispatch 方法你的应用程序不会崩溃
异步方法
DispatchQueue.main.async
{
//Write code here
}
同步方法
DispatchQueue.main.sync
{
//Write code here
}
对于Swift 3
DispatchQueue.main.async {
// Write your code here
}
let newQueue = DispatchQueue(label: "newname")
newQueue.sync {
// your code
}
由于上面已经回答了 OP 问题,我只想添加一些速度注意事项:
您在 DispatchQueue.global.
中分配给异步函数的优先级 class 有很大不同我不推荐具有 .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 上最小。
更新 swift 5
Serial Queue
let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
// code to execute
}
Concurrent Queue
let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
concurrentQueue.async {
// code to execute
}
参数
标签
附加到队列的字符串标签,用于在仪器、示例、堆栈快照和崩溃报告等调试工具中唯一标识它。因为应用程序、库和框架都可以创建自己的调度队列,所以建议使用反向 DNS 命名样式 (com.example.myqueue)。此参数是可选的,可以为 NULL。
qos
与队列关联的服务质量级别。该值决定了系统调度任务执行的优先级。有关可能值的列表,请参阅 DispatchQoS.QoSClass.
属性
与队列关联的属性。包括 concurrent 属性来创建一个并发执行任务的调度队列。如果省略该属性,调度队列将串行执行任务。
autoreleaseFrequency
自动释放由队列调度的块创建的对象的频率。有关可能值的列表,请参阅 DispatchQueue.AutoreleaseFrequency.
目标
执行块的目标队列。如果您希望系统提供适合当前对象的队列,请指定DISPATCH_TARGET_QUEUE_DEFAULT。