一尘不染

在Swift 3,Swift 4及更高版本中,我该如何使用dispatch_sync,dispatch_async,dispatch_after等?

swift

我在Swift 2.x(甚至1.x)项目中有很多代码,如下所示:

// Move to a background thread to do some long running work
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    let image = self.loadOrGenerateAnImage()
    // Bounce back to the main thread to update the UI
    dispatch_async(dispatch_get_main_queue()) {
        self.imageView.image = image
    }
}

或类似这样的东西来延迟执行:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
    print("test")
}

或Grand Central Dispatch API的所有其他各种用途…

既然我已经在Swift 3的Xcode
8(测试版)中打开了我的项目,就会遇到各种各样的错误。其中一些提供了修复我的代码的功能,但并非所有修复都可以产生有效的代码。我该怎么办?


阅读 441

收藏
2020-07-07

共1个答案

一尘不染

从一开始,Swift就提供了一些使ObjC和C更加Swifty的功能,并为每个版本增加了更多功能。现在,在Swift
3中,新的“以成员身份导入”功能使具有某些样式的C
API的框架(其中您具有类似类的数据类型,以及可以使用的一系列全局函数)行为更像Swift原生API。数据类型作为Swift类导入,它们的相关全局函数作为这些类上的方法和属性导入,并且一些相关的东西(如常量集)可以在适当的时候成为子类型。

在Xcode 8 / Swift 3 beta中,Apple应用了此功能(以及其他一些功能)来使Dispatch框架更加迅速。(还有Core
Graphics
。)如果您一直在关注Swift开源工作,这不是新闻,但现在是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常量之一。服务质量(QoS)说明符是在OS X
10.10 / iOS
8.0中引入的,它为系统确定工作的优先级和弃用旧优先级说明符提供了更清晰的方法。有关详细信息,请参阅Apple的有关后台工作和能源效率文档

顺便说一句,如果您要保留自己的队列来组织工作,那么现在就可以这样获得通知(注意DispatchQueueAttributesOptionSet,因此您可以使用集合样式的文字来组合选项):

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的界面来找到自己的出路-
使用“快速打开”找到Dispatch模块,或DispatchQueue在您的Swift项目/操场中放一个符号(如)并单击鼠标,然后在其中浏览从那里的模块。(您可以在Apple新颖的API参考网站和in-
Xcode文档查看器中找到Swift Dispatch
API,但看来C版本的文档内容尚未移入其中。)

有关更多提示,请参见《迁移指南》

2020-07-07