我在Swift 2.x(甚至1.x)项目中有很多代码,如下所示:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
print("test")
}
这样的东西可以延迟执行:
{{1}}
或者Grand Central Dispatch API的所有其他用途......
既然我已经在Swift 3的Xcode 8(测试版)中打开了我的项目,我就会遇到各种错误。其中一些提供修复我的代码,但并非所有修复产生工作代码。我该怎么办?
答案 0 :(得分:322)
从一开始,Swift就提供了一些使ObjC和C更加Swifty的工具,每个版本都增加了更多。现在,在Swift 3中,新的"import as member"特性允许具有某些样式的C API的框架 - 您有一种类似于类的数据类型,以及一组可以使用它的全局函数 - 更像是Swift原生API。数据类型作为Swift类导入,它们的相关全局函数作为这些类的方法和属性导入,并且一些相关的事物(如常量集)可以在适当的时候成为子类型。
在Xcode 8 / Swift 3 beta中,Apple已应用此功能(以及其他一些功能)使Dispatch框架更加快速。 (还有Core Graphics。)如果你一直在关注Swift开源工作this isn't news,但现在它是第一次成为Xcode的一部分。
将任何项目移至Swift 3 的第一步应该是在Xcode 8中打开它并选择编辑>转换>菜单中的当前Swift语法... 。这将适用于(通过您的审核和批准)所有重命名的API和其他更改所需的所有更改。 (通常,一行代码会同时受到多个这些更改的影响,因此响应错误修复 - 它可能无法正确处理所有内容。)
结果是,将工作弹回到后台和后面的常见模式现在看起来像这样:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.imageView.image = image
}
}
请注意,我们正在使用.userInitiated
而不是旧的DISPATCH_QUEUE_PRIORITY
常量之一。 OS X 10.10 / iOS 8.0中引入了服务质量(QoS)说明符,为系统确定工作优先级和弃用旧优先级说明符提供了更清晰的方法。有关详细信息,请参阅Apple的docs on background work and energy efficiency。
顺便说一句,如果您要保留自己的队列来组织工作,现在获取一个队列的方式如下(请注意DispatchQueueAttributes
是OptionSet
,因此您使用集合用于组合选项的样式文字:
class Foo {
let queue = DispatchQueue(label: "com.example.my-serial-queue",
attributes: [.serial, .qosUtility])
func doStuff() {
queue.async {
print("Hello World")
}
}
}
使用dispatch_after
稍后再开始工作?这也是队列上的一种方法,它需要一个DispatchTime
,它有各种数字类型的运算符,因此您只需添加整数或小数秒:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
print("Are we there yet?")
}
您可以通过在Xcode 8中打开其界面来找到新的Dispatch API的方法 - 使用Open Quickly查找Dispatch模块,或在Swift项目/游乐场中放置符号(如DispatchQueue
)命令 - 单击它,然后从那里围绕模块发出骚扰。 (您可以在Apple的spiffy新API参考网站和in-Xcode文档查看器中找到Swift Dispatch API,但看起来C版本的文档内容还没有进入它爱好。)
有关更多提示,请参阅Migration Guide。
答案 1 :(得分:133)
在Xcode 8中,beta 4不起作用......
使用:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
print("Are we there yet?")
}
对于异步两种方式:
DispatchQueue.main.async {
print("Async1")
}
DispatchQueue.main.async( execute: {
print("Async2")
})
答案 2 :(得分:67)
这是关于Swift 4
的{{1}}的好例子:
async
答案 3 :(得分:37)
在Xcode 8中使用:
DispatchQueue.global(qos: .userInitiated).async { }
答案 4 :(得分:20)
主要和后台队列
let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread")
使用异步和同步线程!
background.async { //async tasks here }
background.sync { //sync tasks here }
异步线程将与主线程一起使用。
同步线程将在执行时阻塞主线程。
答案 5 :(得分:6)
迅速4.1。我们在代码的许多地方使用队列。因此,我创建了具有所有队列的Threads类。如果您不想使用Threads类,则可以从类方法中复制所需的队列代码。
class Threads {
static let concurrentQueue = DispatchQueue(label: "AppNameConcurrentQueue", attributes: .concurrent)
static let serialQueue = DispatchQueue(label: "AppNameSerialQueue")
// Main Queue
class func performTaskInMainQueue(task: @escaping ()->()) {
DispatchQueue.main.async {
task()
}
}
// Background Queue
class func performTaskInBackground(task:@escaping () throws -> ()) {
DispatchQueue.global(qos: .background).async {
do {
try task()
} catch let error as NSError {
print("error in background thread:\(error.localizedDescription)")
}
}
}
// Concurrent Queue
class func perfromTaskInConcurrentQueue(task:@escaping () throws -> ()) {
concurrentQueue.async {
do {
try task()
} catch let error as NSError {
print("error in Concurrent Queue:\(error.localizedDescription)")
}
}
}
// Serial Queue
class func perfromTaskInSerialQueue(task:@escaping () throws -> ()) {
serialQueue.async {
do {
try task()
} catch let error as NSError {
print("error in Serial Queue:\(error.localizedDescription)")
}
}
}
// Perform task afterDelay
class func performTaskAfterDealy(_ timeInteval: TimeInterval, _ task:@escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: (.now() + timeInteval)) {
task()
}
}
}
显示使用主队列的示例。
override func viewDidLoad() {
super.viewDidLoad()
Threads.performTaskInMainQueue {
self.tblViewSignUP.reloadData()
}
}