我如何在 Swift 3、Swift 4 及更高版本中 dispatch_sync、dispatch_async、dispatch_after 等? [英] How do I dispatch_sync, dispatch_async, dispatch_after, etc in Swift 3, Swift 4, and beyond?

查看:28
本文介绍了我如何在 Swift 3、Swift 4 及更高版本中 dispatch_sync、dispatch_async、dispatch_after 等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have lots of code in Swift 2.x (or even 1.x) projects that looks like this:

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

或者像这样的东西来延迟执行:

Or stuff like this to delay execution:

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

或 Grand Central Dispatch API 的任何其他用途...

Or any of all kinds of other uses of the Grand Central Dispatch API...

现在我已经在 Swift 3 的 Xcode 8(测试版)中打开了我的项目,我遇到了各种错误.其中一些提供修复我的代码,但并非所有修复都生成工作代码.我该怎么办?

Now that I've opened my project in Xcode 8 (beta) for Swift 3, I get all kinds of errors. Some of them offer to fix my code, but not all of the fixes produce working code. What do I do about this?

推荐答案

从一开始,Swift 就提供了一些使 ObjC 和 C 更加 Swifty 的工具,每个版本都增加了更多.现在,在 Swift 3 中,新的 "import as member" 特性让具有特定风格的 C API 的框架——你的数据类型有点像一个类,还有一堆全局函数来处理它——表现得更像 Swift——原生 API.数据类型作为 Swift 类导入,它们相关的全局函数作为这些类的方法和属性导入,一些相关的东西(如常量集)可以在适当的时候成为子类型.

Since the beginning, Swift has provided some facilities for making ObjC and C more Swifty, adding more with each version. Now, in Swift 3, the new "import as member" feature lets frameworks with certain styles of C API -- where you have a data type that works sort of like a class, and a bunch of global functions to work with it -- act more like Swift-native APIs. The data types import as Swift classes, their related global functions import as methods and properties on those classes, and some related things like sets of constants can become subtypes where appropriate.

在 Xcode 8/Swift 3 beta 中,Apple 已应用此功能(以及其他一些功能)使 Dispatch 框架更加 Swifty.(还有核心图形.)如果您一直在关注 Swift 的开源工作,这不是新闻,但现在是它第一次成为 Xcode 的一部分.

In Xcode 8 / Swift 3 beta, Apple has applied this feature (along with a few others) to make the Dispatch framework much more Swifty. (And Core Graphics, too.) If you've been following the Swift open-source efforts, this isn't news, but now is the first time it's part of Xcode.

将任何项目移动到 Swift 3 的第一步应该是在 Xcode 8 中打开它并选择 Edit > Convert > To Current Swift Syntax...菜单.这将立即应用(经过您的审查和批准)所有重命名的 API 和其他更改所需的所有更改.(通常,一行代码同时受到多个更改的影响,因此对错误修复做出响应 - 单独处理可能无法正确处理所有事情.)

Your first step on moving any project to Swift 3 should be to open it in Xcode 8 and choose Edit > Convert > To Current Swift Syntax... in the menu. This will apply (with your review and approval) all of the changes at once needed for all the renamed APIs and other changes. (Often, a line of code is affected by more than one of these changes at once, so responding to error fix-its individually might not handle everything right.)

结果是将工作跳到后台和返回的常见模式现在看起来像这样:

The result is that the common pattern for bouncing work to the background and back now looks like this:

// 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 的 有关后台工作和能源效率的文档了解详情.

Note we're using .userInitiated instead of one of the old DISPATCH_QUEUE_PRIORITY constants. Quality of Service (QoS) specifiers were introduced in OS X 10.10 / iOS 8.0, providing a clearer way for the system to prioritize work and deprecating the old priority specifiers. See Apple's docs on background work and energy efficiency for details.

顺便说一下,如果您保留自己的队列来组织工作,那么现在获取队列的方法如下所示(注意 DispatchQueueAttributes 是一个 OptionSet,所以你使用集合样式的文字来组合选项):

By the way, if you're keeping your own queues to organize work, the way to get one now looks like this (notice that DispatchQueueAttributes is an OptionSet, so you use collection-style literals to combine options):

class Foo { 
    let queue = DispatchQueue(label: "com.example.my-serial-queue",
                           attributes: [.serial, .qosUtility])
    func doStuff() {
        queue.async {
            print("Hello World")
        }
    }
}

使用 dispatch_after 来做以后的工作?这也是队列上的一种方法,它需要一个 DispatchTime,它具有用于各种数字类型的运算符,因此您可以添加整数或小数秒:

Using dispatch_after to do work later? That's a method on queues, too, and it takes a DispatchTime, which has operators for various numeric types so you can just add whole or fractional seconds:

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)/playground 并命令单击它,然后从那里浏览模块.(您可以在 Apple 漂亮的新 API 参考网站和 Xcode 文档查看器中找到 Swift Dispatch API,但似乎 C 版本的文档内容尚未移入其中.)

You can find your way around the new Dispatch API by opening its interface in Xcode 8 -- use Open Quickly to find the Dispatch module, or put a symbol (like DispatchQueue) in your Swift project/playground and command-click it, then brouse around the module from there. (You can find the Swift Dispatch API in Apple's spiffy new API Reference website and in-Xcode doc viewer, but it looks like the doc content from the C version hasn't moved into it just yet.)

有关更多提示,请参阅迁移指南.

See the Migration Guide for more tips.

这篇关于我如何在 Swift 3、Swift 4 及更高版本中 dispatch_sync、dispatch_async、dispatch_after 等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆