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

或任何其他类型的大中央调度API的使用…

现在我已经在Xcode 8(测试版)中为Swift 3打开了我的项目,我得到了各种各样的错误。他们中的一些人愿意修复我的代码,但并不是所有的修复都能产生工作代码。我该怎么办?


当前回答

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测试版中,苹果应用了这个功能(以及其他一些功能),使Dispatch框架更加Swifty。(还有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常量之一。在OS X 10.10 / iOS 8.0中引入了服务质量(QoS)说明符,为系统提供了一种更清晰的方式来对工作进行优先级划分,并弃用了旧的优先级说明符。详情请参阅苹果公司的背景工作和能源效率文件。

顺便说一下,如果你保持你自己的队列来组织工作,现在获得一个队列的方式看起来像这样(注意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中打开它的接口来找到新的分派API——使用“快速打开”来找到分派模块,或者在你的Swift项目/操场上放一个符号(比如DispatchQueue),然后命令点击它,然后从那里浏览模块。(你可以在苹果漂亮的新API参考网站和xcode文档查看器中找到Swift Dispatch API,但看起来C版本的文档内容还没有移动到它中。)

有关更多技巧,请参阅迁移指南。

其他回答

Swift 4.1和5。我们在代码中的许多地方都使用了队列。因此,我创建了带有所有队列的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 {
        //Update UI
    }
}

在Xcode 8中使用:

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

这是Swift 4关于async的一个很好的例子:

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

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测试版中,苹果应用了这个功能(以及其他一些功能),使Dispatch框架更加Swifty。(还有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常量之一。在OS X 10.10 / iOS 8.0中引入了服务质量(QoS)说明符,为系统提供了一种更清晰的方式来对工作进行优先级划分,并弃用了旧的优先级说明符。详情请参阅苹果公司的背景工作和能源效率文件。

顺便说一下,如果你保持你自己的队列来组织工作,现在获得一个队列的方式看起来像这样(注意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中打开它的接口来找到新的分派API——使用“快速打开”来找到分派模块,或者在你的Swift项目/操场上放一个符号(比如DispatchQueue),然后命令点击它,然后从那里浏览模块。(你可以在苹果漂亮的新API参考网站和xcode文档查看器中找到Swift Dispatch API,但看起来C版本的文档内容还没有移动到它中。)

有关更多技巧,请参阅迁移指南。

在Xcode 8 beta 4不工作…

Use:

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

对于async有两种方式:

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

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