如何在Swift 3、Swift 4和其他版本中分派_sync、dispatch_async、dispatch_after等?

时间:2022-12-11 16:55:06

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

我有很多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
    }
}

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")
}

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

或任何其他用途的大*调度API…

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?

现在我已经在Xcode 8 (beta)中为Swift 3打开了我的项目,我得到了各种各样的错误。其中一些提供修复我的代码,但不是所有的修复都会产生工作代码。我该怎么办?

5 个解决方案

#1


292  

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.

从一开始,Swift就为ObjC和C提供了一些便利,每个版本都增加了更多内容。现在,在Swift 3中,新的“作为成员的导入”特性让具有特定风格的C API框架(其中有一种类似类的数据类型,以及一组用于处理它的全局函数)更像Swift本地API。数据类型作为Swift类导入,它们的相关全局函数作为这些类的方法和属性导入,以及一些相关的东西,如常量集,可以在适当的情况下成为子类型。

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.

在Xcode 8 / Swift 3 beta版中,苹果应用了这个特性(以及其他一些特性),使分派框架更加敏捷。(和核心图形。)如果您一直在遵循Swift开源的努力,这不是新闻,但现在是第一次它是Xcode的一部分。

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.)

将任何项目转移到Swift 3的第一步应该是在Xcode 8中打开它,并选择Edit >将>转换为当前的Swift语法……在菜单。这将应用(经过您的审查和批准)所有重命名的api和其他更改所需的所有更改。(通常情况下,一行代码会同时受到多个更改的影响,因此对错误进行响应可能不能正确处理所有问题)。

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

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.

注意,我们使用的是. userinitiative,而不是一个旧的DISPATCH_QUEUE_PRIORITY常量。在OS X 10.10 / ios8.0中引入了服务质量(QoS)说明,为系统优化工作和对旧的优先级说明提供了更清晰的方法。详情请参阅苹果公司关于背景工作和能源效率的文档。

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):

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

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

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:

使用dispatch_after进行后续工作?这也是一个关于队列的方法,它需要一个调度时间,它有各种数字类型的操作符,所以你可以只添加整秒或小数秒:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
    print("Are we there yet?")
}

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.)

通过在Xcode 8中打开它的接口,您可以找到新的分派API——使用Open快速找到分派模块,或者在Swift项目/游乐场中放置一个符号(如DispatchQueue),然后单击它,然后在模块周围启动。(你可以在苹果最新的API参考网站和in- xcode doc查看器中找到Swift Dispatch API,但看起来C版本的doc内容还没有进入。)

See the Migration Guide for more tips.

请参阅迁移指南以获得更多提示。

#2


116  

in xcode 8 beta 4 does not work.. Use:

在xcode 8 beta 4中不工作。使用:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    print("Are we there yet?")
}

for async two ways:

异步两种方式:

DispatchQueue.main.async {
    print("Async1")
}

DispatchQueue.main.async( execute: {
    print("Async2")
})

#3


52  

This one is good example for Swift 4 about async:

这是关于异步的一个很好的例子:

DispatchQueue.global(qos: .background).async {
    // Background Thread
    DispatchQueue.main.async {
        // Run UI Updates or call completion block
    }
}

#4


33  

in xcode8 use:

在xcode8使用:

DispatchQueue.global(qos: .userInitiated).async { }

#5


12  

Swift 4

Main and Background Queues

主要和背景队列

let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread") 

Working with async and sync threads!

使用异步和同步线程!

 background.async { //async tasks here } 
 background.sync { //sync tasks here } 

Async threads will work along with the main thread.

异步线程将与主线程一起工作。

Sync threads will block the main thread while executing.

同步线程将在执行时阻塞主线程。

#1


292  

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.

从一开始,Swift就为ObjC和C提供了一些便利,每个版本都增加了更多内容。现在,在Swift 3中,新的“作为成员的导入”特性让具有特定风格的C API框架(其中有一种类似类的数据类型,以及一组用于处理它的全局函数)更像Swift本地API。数据类型作为Swift类导入,它们的相关全局函数作为这些类的方法和属性导入,以及一些相关的东西,如常量集,可以在适当的情况下成为子类型。

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.

在Xcode 8 / Swift 3 beta版中,苹果应用了这个特性(以及其他一些特性),使分派框架更加敏捷。(和核心图形。)如果您一直在遵循Swift开源的努力,这不是新闻,但现在是第一次它是Xcode的一部分。

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.)

将任何项目转移到Swift 3的第一步应该是在Xcode 8中打开它,并选择Edit >将>转换为当前的Swift语法……在菜单。这将应用(经过您的审查和批准)所有重命名的api和其他更改所需的所有更改。(通常情况下,一行代码会同时受到多个更改的影响,因此对错误进行响应可能不能正确处理所有问题)。

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

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.

注意,我们使用的是. userinitiative,而不是一个旧的DISPATCH_QUEUE_PRIORITY常量。在OS X 10.10 / ios8.0中引入了服务质量(QoS)说明,为系统优化工作和对旧的优先级说明提供了更清晰的方法。详情请参阅苹果公司关于背景工作和能源效率的文档。

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):

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

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

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:

使用dispatch_after进行后续工作?这也是一个关于队列的方法,它需要一个调度时间,它有各种数字类型的操作符,所以你可以只添加整秒或小数秒:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
    print("Are we there yet?")
}

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.)

通过在Xcode 8中打开它的接口,您可以找到新的分派API——使用Open快速找到分派模块,或者在Swift项目/游乐场中放置一个符号(如DispatchQueue),然后单击它,然后在模块周围启动。(你可以在苹果最新的API参考网站和in- xcode doc查看器中找到Swift Dispatch API,但看起来C版本的doc内容还没有进入。)

See the Migration Guide for more tips.

请参阅迁移指南以获得更多提示。

#2


116  

in xcode 8 beta 4 does not work.. Use:

在xcode 8 beta 4中不工作。使用:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    print("Are we there yet?")
}

for async two ways:

异步两种方式:

DispatchQueue.main.async {
    print("Async1")
}

DispatchQueue.main.async( execute: {
    print("Async2")
})

#3


52  

This one is good example for Swift 4 about async:

这是关于异步的一个很好的例子:

DispatchQueue.global(qos: .background).async {
    // Background Thread
    DispatchQueue.main.async {
        // Run UI Updates or call completion block
    }
}

#4


33  

in xcode8 use:

在xcode8使用:

DispatchQueue.global(qos: .userInitiated).async { }

#5


12  

Swift 4

Main and Background Queues

主要和背景队列

let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread") 

Working with async and sync threads!

使用异步和同步线程!

 background.async { //async tasks here } 
 background.sync { //sync tasks here } 

Async threads will work along with the main thread.

异步线程将与主线程一起工作。

Sync threads will block the main thread while executing.

同步线程将在执行时阻塞主线程。