コードをXcode 8.0 beta 6に更新しましたが、新しい非エスケープクロージャーのデフォルトに関するものに固執しました。次のコードでは、Xcodeは、以下のコードの最初の行の@escaping
の前にcompletion:
を追加することを提案していますが、それでもコンパイルされず、円になります。 *
(EDIT:実際には、Xcodeが示唆するように、aftercompletion:
に@escapingを追加する必要があります。アラートは表示されますが、クリーニングとコンパイルにより削除されます。)*更新されたSwift 3で動作するように、このコードをどのように再作成/修正する必要がありますか?新しいマニュアルを確認しましたが、適切なコードサンプルが見つかりませんでした。
func doSomething(withParameter parameter: Int, completion: () -> ()) {
// Does something
callSomeOtherFunc(withCompletion: completion)
}
// Calling the method and execute closure
doSomething(withParameter: 2) {
// do things in closure
}
助けていただければ幸いです!
Swift 3より前は、クロージャー属性@autoclosure
および@noescape
はクロージャーparameterの属性でしたが、現在はパラメーターtype;次の承認済みSwift進化の提案を参照してください。
特定の質問は、パラメータタイプ属性@escaping
(同じ新しいルールが適用されます)に関係します。これは、受け入れられたSwift進化の提案で説明されているように、デフォルトでクロージャパラメータをエスケープしないようにします。
これらの提案は現在、Xcode 8のベータ段階で実装されています( Xcode 8ベータ6のリリースノート ;アクセスには開発者アカウントログインが必要です)
Xcode 8ベータ6の新機能-Swiftコンパイラ:Swift言語
閉鎖パラメーターは、
@noescape
で明示的に注釈が付けられるのではなく、デフォルトでは非エスケープです。@escaping
を使用して、クロージャーパラメーターがエスケープされる可能性があることを示します。@autoclosure(escaping)
は、@autoclosure @escaping
として記述されています。注釈@noescape
および@autoclosure(escaping)
は非推奨です。 (SE-0103)...
Xcode 8ベータ版の新機能– SwiftおよびApple LLVMコンパイラ:Swift言語
@noescape
および@autoclosure
属性は、パラメーター名の前ではなく、パラメータータイプの前に記述する必要があります。 [SE-0049]
したがって、次のようにデフォルト以外の@escaping
属性を使用します。パラメーター自体ではなく、クロージャーパラメーターのtypeに適用されます
func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}
(コメントはSOに関する永続的なデータではないため、以下の投票されたコメントの質問に対する私の答えを含む)
@Cristi Băluță: "エスケープは何をしますか?Swift3自動変換の前にこのキーワードを見たことはありません..."
例参照 上記のSE-0103進化の提案 へのリンク(およびベータ6リリースノートの引用テキスト):以前は、クロージャーパラメーターはデフォルトでエスケープされていました(したがって、明示的に存在する必要はありません)エスケープ用のアノテーション)が、デフォルトでは代わりに非エスケープになりました。したがって、@escaping
を追加して、クロージャーパラメーターがエスケープする可能性があることを明示的に注釈します(既定の動作とは逆)。これはまた、@noescape
が非推奨になった理由を説明します(デフォルトの動作に注釈を付ける必要はありません)。
クロージャーパラメーターがエスケープしていることの意味を説明するために、 言語リファレンス-属性 を引用しています。
「メソッドまたは関数宣言のパラメーターの型にこの属性を適用して、後で実行するためにパラメーターの値を保存できることを示します。つまり、この値は呼び出しの存続期間を超えます。」
@noescape
Xcode 8ベータ6以降@noescape
がデフォルトです。それ以前は、@escaping
がデフォルトでした。以前のバージョンからSwift 3.0に更新する人は誰でもこのエラーに直面する可能性があります。
@noescape
クロージャーを変数内に保存することはできません。なぜなら、変数内にクロージャーを格納できるなら、コードのどこからでもクロージャーを実行できるからです。ただし、@noescape
は、クロージャーパラメーターが関数の本体をエスケープできないことを示しています。
これにより、Xcode 8でコンパイラエラーが発生します。
class MyClass {
var myClosure: (() -> ())?
func doSomething(finishBlock: () -> ()) {
myClosure = finishBlock // ‼️ Error: Assigning non-escaping parameter 'finishBlock' to an @escaping closure
}
}
これでコンパイルできます(明示的に@escaping
と記述します)
class MyClass {
var myClosure: (() -> ())?
func doSomething(finishBlock: @escaping () -> ()) {
myClosure = finishBlock
}
}
@noescape
の利点:
詳細については、以下を参照してください。 非エスケープクロージャをデフォルトにする