1. ホーム
  2. swift

[解決済み] Swift 3でdispatch_onceはどうなる?

2022-02-16 22:40:35

質問

さて、そこで私は新しい SwiftyディスパッチAPI Xcode 8に搭載されました。を使って楽しんでいます。 DispatchQueue.main.async をブラウズしています。 Dispatch モジュールを使って、新しいAPIをすべて見つけることができます。

しかし、私はまた dispatch_once シングルトンの作成やワンタイムセットアップのようなものが(マルチスレッド環境であっても)複数回実行されないようにするため...そして dispatch_once は、新しい Dispatch モジュールにはどこにもないのですか?

static var token: dispatch_once_t = 0
func whatDoYouHear() {
    print("All of this has happened before, and all of it will happen again.")
    dispatch_once(&token) {
        print("Except this part.")
    }
}

解決方法は?

Swift 1.x以降、Swiftは dispatch_once 舞台裏 を使用して、グローバル変数と静的プロパティのスレッドセーフな遅延初期化を実行します。

そのため static var は、すでに dispatch_once のトークンとして使用するのは、ちょっと変ですね。 dispatch_once . 実際、安全な方法はありません。 dispatch_once このような再帰性を排除するために、廃止されたのです。その代わり、その上に構築された言語機能を使うだけでいいんです。

// global constant: SomeClass initializer gets called lazily, only on first use
let foo = SomeClass()

// global var, same thing happens here
// even though the "initializer" is an immediately invoked closure
var bar: SomeClass = {
    let b = SomeClass()
    b.someProperty = "whatever"
    b.doSomeStuff()
    return b
}()

// ditto for static properties in classes/structures/enums
class MyClass {
    static let singleton = MyClass()
    init() {
        print("foo")
    }
}

ということで、これまで使っていた dispatch_once 一回限りの 初期化 その値をグローバル変数や静的プロパティとして初期化すればよいのです。

しかし、もしあなたが dispatch_once 必ずしも結果が出るとは限らない仕事をするために?グローバル変数や静的プロパティを使っても、そのようなことは可能です。 Void :

let justAOneTimeThing: () = {
    print("Not coming back here.")
}()

また、グローバル変数や静的プロパティにアクセスして一回限りの作業を行うのが気に入らない場合、例えば、クライアントがあなたのライブラリを操作する前に "initialize me" 関数を呼び出したい場合、そのアクセスを関数でラップすれば良いのです。

func doTheOneTimeThing() {
    justAOneTimeThing
}

をご覧ください。 移行ガイド をご覧ください。