[解決済み] エスケープしないパラメータをクロージャで使用すると、エスケープされることがある
2022-04-21 08:53:11
質問
プロトコルがあります。
enum DataFetchResult {
case success(data: Data)
case failure
}
protocol DataServiceType {
func fetchData(location: String, completion: (DataFetchResult) -> (Void))
func cachedData(location: String) -> Data?
}
実装例付き。
/// An implementation of DataServiceType protocol returning predefined results using arbitrary queue for asynchronyous mechanisms.
/// Dedicated to be used in various tests (Unit Tests).
class DataMockService: DataServiceType {
var result : DataFetchResult
var async : Bool = true
var queue : DispatchQueue = DispatchQueue.global(qos: .background)
var cachedData : Data? = nil
init(result : DataFetchResult) {
self.result = result
}
func cachedData(location: String) -> Data? {
switch self.result {
case .success(let data):
return data
default:
return nil
}
}
func fetchData(location: String, completion: (DataFetchResult) -> (Void)) {
// Returning result on arbitrary queue should be tested,
// so we can check if client can work with any (even worse) implementation:
if async == true {
queue.async { [weak self ] in
guard let weakSelf = self else { return }
// This line produces compiler error:
// "Closure use of non-escaping parameter 'completion' may allow it to escape"
completion(weakSelf.result)
}
} else {
completion(self.result)
}
}
}
上記のコードはSwift3(Xcode8-beta5)でコンパイルして動作していましたが、beta6で動作しなくなりました。根本的な原因を指摘してもらえますか?
解決方法を教えてください。
これは、関数型のパラメーターのデフォルトの動作が変更されたためです。Swift 3 (特に Xcode 8 beta 6 に同梱されているビルド) よりも前に、それらはエスケープされることがデフォルトでした。
@noescape
これは、関数呼び出しの期間より長くならないことを保証するものです。
しかし、現在
@noescape
は関数型パラメータに対するデフォルトです。このような関数を保存したり、取り込んだりしたい場合は、以下のようにマークする必要があります。
@escaping
:
protocol DataServiceType {
func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void)
func cachedData(location: String) -> Data?
}
func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void) {
// ...
}
をご覧ください。 Swift Evolutionの提案 は、この変更に関する詳細な情報を提供します。
関連
-
[解決済み] iPhone Simulator.appと一緒にXcodeも外付けハードディスクにインストールできますか?
-
[解決済み] Swiftで乱数を生成する方法とは?
-
[解決済み] Swiftでdispatch_onceのシングルトンモデルを使う
-
[解決済み] 2倍値を小数点以下x桁に丸める処理を素早く行う。
-
[解決済み] Swiftではクロージャの内部では常に[unowned self]を使うべきか?
-
[解決済み] Swift で app delegate への参照を取得するにはどうすればよいですか?
-
[解決済み] PHPでは、クロージャとは何ですか?なぜ "use "識別子を使用するのですか?
-
[解決済み】JavaScriptでクロージャの実用的な使い方は?
-
[解決済み】ReactiveCocoaとRxSwiftの比較 - 長所と短所?
-
[解決済み] Swift のオプションのエスケープクロージャーパラメータ
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 使用しているSwiftのバージョンを確認するにはどうすればよいですか?
-
[解決済み] Swiftでコアデータを日付(時間だけでなく)でソートする
-
[解決済み] Swiftでdispatch_onceのシングルトンモデルを使う
-
[解決済み] Swift: print() vs println() vs NSLog()
-
[解決済み] Swiftの'open'キーワードは何ですか?
-
[解決済み】==と===の違いについて
-
[解決済み】Swiftでボタンに丸みを帯びたボーダーを付けるにはどうすればいいですか?
-
[解決済み】解決方法。iOS 13.0で'keyWindow'が非推奨になりました。
-
[解決済み】swift 4でenumをDecodableにするにはどうすればいいですか?
-
[解決済み】Swiftの列挙型と関連する値の等質性をテストする方法