web-dev-qa-db-ja.com

Swift 3、Swift 4、およびそれ以降のバージョンでdispatch_sync、dispatch_async、dispatch_afterなどをどのようにしたらできますか。

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(beta)でプロジェクトを開いたので、今度はあらゆる種類のエラーが発生します。そのうちのいくつかは私のコードを修正することを申し出ますが、すべての修正が実用的なコードを生成するわけではありません。私はこれについて何をしますか?

220
rickster

当初から、SwiftはObjCとCをより迅速にするための機能を提供しており、各バージョンにさらに追加しています。現在、Swift 3では、新しい "メンバーとしてインポート" 機能により、特定のスタイルのC APIを備えたフレームワークが可能になります。 、およびそれと連携する一連のグローバル関数-より多くのSwiftネイティブAPIのように動作します。データ型はSwiftクラスとしてインポートされ、それらの関連するグローバル関数はそれらのクラスのメソッドおよびプロパティとしてインポートされ、定数のセットなどの関連するものは適切なサブタイプになります。

Xcode 8/Swift 3ベータ版では、Appleがこの機能を(他のいくつかと一緒に)適用して、Dispatchフレームワークをより迅速にしました。 (そして Core Graphics も。)もしあなたがSwiftオープンソースの努力を続けてきたなら、 これはニュースではありません ですが、今はそうです初めてXcodeの一部になります。

プロジェクトをSwift 3に移動する最初のステップは、Xcode 8でプロジェクトを開いて編集>変換>現在のSwift構文...メニューで。これは、名前の変更されたすべてのAPIおよびその他の変更に必要なすべての変更を(確認と承認を伴って)適用します。 (多くの場合、1行のコードがこれらの変更の1つ以上の影響を一度に受けるため、エラー修正に対応することは、個々にすべてを正しく処理できない場合があります。)

その結果、作業を背景に戻したり戻したりするための一般的なパターンは次のようになります。

// 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を使用していることに注意してください。 Quality of Service(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?")
}

新しいDispatch APIを回避するには、Xcode 8でインターフェイスを開きます。OpenQuicklyを使用してDispatchモジュールを見つけるか、Swiftプロジェクトにシンボル(DispatchQueueなど)を配置します。/playgroundをクリックし、コマンドキーを押しながらクリックして、そこからモジュールをブラウジングします。 (Swift Dispatch APIはAppleの新しいAPIリファレンスWebサイトとXcode内のドキュメントビューアーにありますが、Cバージョンのドキュメントコンテンツは移動していないようです。まだそれに。)

その他のヒントについては、 移行ガイド を参照してください。

326
rickster

Xcode 8 beta 4では動作しません...

つかいます:

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

2つの非同期方法

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

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

これはasyncに関するSwift 4の良い例です:

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

xcode 8では、

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

スイフト4

メインキューとバックグラウンドキュー

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

Asyncと sync threadsを使用してください。

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

非同期スレッドはメインスレッドと共に動作します。

同期スレッドは実行中にメインスレッドをブロックします。

20
Saranjith

スイフト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()
    }
}
6
GSK