1. ホーム
  2. swift

Swift 1.2 の @noescape 属性

2023-10-03 23:42:20

質問

Swift 1.2には関数のクロージャパラメータで新しい属性があり、ドキュメントに書いてある通りです。

これは パラメータはこれまで呼び出された (または @ noescapeパラメータとして渡される)、つまり、そのパラメータが呼び出しの寿命より長くはならないことを意味します。 のみであることを示します。

私の理解では、それ以前は [weak self] を使ってクロージャにクラスなどの強い参照を持たせず、クロージャの実行時に self を nil かインスタンスにすることができたのですが、今は @noescape は、クラスが非活性化された場合、クロージャが決して実行されないことを意味します。私の理解は正しいのでしょうか?

もし私が正しいなら、なぜ私は @noescape クロージャを使う必要があるのでしょうか?

どのように解決するのですか?

@noescape はこのように使うことができます。

func doIt(code: @noescape () -> ()) {
    /* what we CAN */

    // just call it
    code()
    // pass it to another function as another `@noescape` parameter
    doItMore(code)
    // capture it in another `@noescape` closure
    doItMore {
        code()
    }

    /* what we CANNOT do *****

    // pass it as a non-`@noescape` parameter
    dispatch_async(dispatch_get_main_queue(), code)
    // store it
    let _code:() -> () = code
    // capture it in another non-`@noescape` closure
    let __code = { code() }

    */
}

func doItMore(code: @noescape () -> ()) {}

追加 @noescape をつけることで、クロージャがどこかに保存されたり、後で使われたり、非同期に使われることがないことを保証します。

呼び出し側の視点からは、呼び出された関数内で使用されるか、全く使用されないので、キャプチャされた変数の寿命を気にする必要はありません。また、おまけとして、暗黙のうちに self を使うことができるので self. .

func doIt(code: @noescape () -> ()) {
    code()
}

class Bar {
    var i = 0
    func some() {
        doIt {
            println(i)
            //      ^ we don't need `self.` anymore!
        }
    }
}

let bar = Bar()
bar.some() // -> outputs 0

また、コンパイラの観点からは(ドキュメントにあるように リリースノート ):

これは、いくつかの細かいパフォーマンスの最適化を可能にします。