如何在Swift 3中创建调度队列


403

在Swift 2中,我能够使用以下代码创建队列:

let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)

但这在Swift 3中无法编译。

在Swift 3中编写此代码的首选方式是什么?



Swift 4具有3个额外的参数来创建串行队列。如何使用它们创建串行队列?DispatchQueue.init(label:,qos:,attribute :, autoreleaseFrequency:,target:)
nr5

@ nr5队列默认情况下是串行队列,因此仅DispatchQueue(label: "your-label")用于串行队列就足够了。所有额外的参数都具有默认值。
jbg

Answers:


1131

创建并发队列

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 beta 2:

获取后台线程之一

DispatchQueue.global(qos: .default).async {

}

DispatchQueue.global().async {
    // qos' default value is ´DispatchQoS.QoSClass.default`
}

如果您想了解有关使用这些队列的信息,请参见此答案。


3
您实际上可以attributes: .serial在创建串行队列时忽略:let serialQueue = DispatchQueue(label: "queuename")
基恩,2016年

15
在Xcode 8 beta 4中,没有.serial选项,因此您必须通过在属性中省略.concurrent来创建串行队列。
奥列格·谢尔曼

我需要从Swift3到objc中访问DispatchQueue,但是出现以下错误在执行dispatch_queue_t backgroundQueue时,无法初始化类型为'OS_dispatch_queue * _Nonnull'的右值的'__strong dispatch_queue_t'类型的变量(aka'NSObject <OS_dispatch_queue> * __ strong') = [SwiftClass队列]; 快速地是DispatchQueue的静态变量
ideerge

我在Swift 3.0中尝试了DispatchQueue.global()。asynchronously(DispatchQueue.main){self.mapView.add(self .mapPolyline)},但都显示与“类型为dispathQuoue的值没有异步成员”相同的错误
Abirami Bala

1
从OP的代码中,Apple为什么要重点使用“ com.swift3.imageQueue”。我看到标签分为三个部分。这是为什么?每个部分代表什么?我没有格式
亲爱的,

55

在> = Swift 3下编译。此示例包含我们需要的大多数语法。

QoS-新的服务质量语法

weak 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
            }
        }
    }
}

6
在Swift 3中进行编码时,习惯于压缩和删除先前代码的30%:-)
t1ser

谢谢你的[弱自我]例子!
imike

1
这是更好地guard认为self是不是nil在顶部,因此,如果它都不执行的代码nil,例如,guard strongSelf = self else { return }
Scott Gardner

@ t1您能告诉我在哪里可以找到Swift 3中用代码编写的GCD文档吗?我只找到了用Objective C写的那个。这里有人将我指向WWDC的视频,但是我想阅读带有Swift 3中示例的官方文档,所以找不到它。
bibscy

1
不要.global(qos: .background)用于IO(网络请求)。使用.global(qos: .default).global(qos: .utility)代替。
Pedro Paulo Amorim

28

在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()
            }

        }
    }

}

12

由于上面已经回答了OP问题,所以我只想添加一些速度方面的注意事项:

DispatchQueue.global中分配给异步函数的优先级类别有很大的不同。

我不建议以.background线程优先级运行任务,尤其是在iPhone X上,该任务似乎分配在低功耗内核上。

这是来自计算密集型函数的一些实际数据,该函数从XML文件读取(带有缓冲)并执行数据插值:

设备名称/ 装置技术领域 / .utility / .DEFAULT / .userInitiated / .userInteractive

  1. iPhone X:18.7秒/6.3秒/1.8秒/1.8秒/1.8秒
  2. iPhone 7:4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5s:7.3s / 6.1s / 4.0s / 4.0s / 3.8s

请注意,所有设备的数据集都不相同。它在iPhone X上最大,在iPhone 5s上最小。


1
很棒的信息。帮助了我
Morgz

1
@Myk如果用户已启动和/或正在等待结果,则应使用.userInitiated.userInteractive,以便回溯其他任何操作。在大多数其他情况下,.default将是一个不错的选择。
Cosmin

6

我做到了这一点,如果您想刷新UI来显示新数据而又不会像UITableView或UIPickerView那样引起用户注意,这一点尤其重要。

    DispatchQueue.main.async
 {
   /*Write your thread code here*/
 }

3
 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上填充对象(标签,imageview,textview),请使用Operation Queue


2
   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版本形成了鲜明的对比。


这看起来比我写的还要干净。谢谢。
gosborne3'3

2

迅捷3

您想在快速代码中调用一些闭包,然后您想要在情节提要中进行更改,即任何类型的更改都属于您的应用程序将崩溃的原因

但是您想使用调度方法,您的应用程序将不会崩溃

异步方法

DispatchQueue.main.async 
{
 //Write code here                                   

}

同步方式

DispatchQueue.main.sync 
{
     //Write code here                                  

}

我想在服务调用时使用异步方法,我的代码是DispatchQueue.main.async {让objstory1 = self.storyboard?.instantiateViewController(withIdentifier:“ HomeViewController”)为!HomeViewController _ = self.navigationController?.pushViewController(objstory1,animation:false)}
Amul4608

1
永远不要使用DispatchQueue.main.sync
–rickster77777

主队列上的同步调用肯定会引起问题。
豆腐战士

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
}

这不会创建调度队列,而只会在运行循环中经过一滴答答后将您置于主队列中。
成功


1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }

1

迅速更新5

串行队列

let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
    // code to execute
}

并发队列

let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

concurrentQueue.async {
// code to execute
}

Apple文档

参量

标签

附加到队列的字符串标签,以便在调试工具(如仪器,样本,堆栈快照和崩溃报告)中唯一地标识它。由于应用程序,库和框架都可以创建自己的调度队列,因此建议使用反向DNS命名方式(com.example.myqueue)。此参数是可选的,可以为NULL。

质量

与队列关联的服务质量级别。此值确定系统安排任务执行的优先级。有关可能值的列表,请参见DispatchQoS.QoSClass。

属性

与队列关联的属性。包括并发属性以创建可以同时执行任务的调度队列。如果省略该属性,则分派队列将顺序执行任务。

自动释放频率

自动释放队列调度的块创建的对象的频率。有关可能的值的列表,请参见DispatchQueue.AutoreleaseFrequency

目标

要在其上执行块的目标队列。如果希望系统提供适合当前对象的队列,请指定DISPATCH_TARGET_QUEUE_DEFAULT。


-3

现在很简单:

let serialQueue = DispatchQueue(label: "my serial queue")

默认为串行,要并发,请使用可选属性参数.concurrent


您最好添加来更新答案seiralQueue.async {}。@tylemol
DawnSong

-3
DispatchQueue.main.async(execute: {
   // code
})

感谢您提供此代码段,它可能会立即提供帮助。通过说明为什么这是一个解决问题的好方法,适当的解释将大大提高其教育价值,并且对将来有相似但不相同的问题的读者来说更有用。请编辑您的答案以添加说明,并指出适用的限制和假设。
Toby Speight

-4

您可以在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*/
}

1
抱歉,这不是在创建调度队列,而是在运行循环中滴答一声之后访问主队列。
成功
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.