クロージャは変異する自己パラメータを暗黙のうちに捕らえることはできない
質問
Firebaseを使ってイベントを監視し、補完ハンドラ内に画像を設定しています。
FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let _ = snapshot.value as? NSNull {
self.img = UIImage(named:"Some-image")!
} else {
self.img = UIImage(named: "some-other-image")!
}
})
しかし、このようなエラーが発生します。
クロージャは変異する自己パラメータを暗黙的に捕捉することはできない
このエラーの意味がよくわからず、解決策を探しても解決しません
どのように解決するのですか?
ショートバージョン
への呼び出しを所有するタイプは
FirebaseRef.observeSingleEvent(of:with:)
は値型である可能性が高いです(
struct
を明示的にキャプチャしない場合があります。
self
を
@escaping
のクロージャになります。
単純な解決策は、所有する型を一度参照に更新することです(
class
).
ロングバージョン
この
observeSingleEvent(of:with:)
というメソッドがあり、Firebaseの
は次のように宣言されています。
func observeSingleEvent(of eventType: FIRDataEventType, with block: @escaping (FIRDataSnapshot) -> Void)
は
block
クロージャは
@escaping
パラメータ属性でマークされており、関数のボディをエスケープすることができます。
self
の寿命さえも逃がしてしまう可能性があるということです (あなたの文脈では)。この知識を使って、より最小限の例を構築し、分析することができます。
struct Foo {
private func bar(with block: @escaping () -> ()) { block() }
mutating func bax() {
bar { print(self) } // this closure may outlive 'self'
/* error: closure cannot implicitly capture a
mutating self parameter */
}
}
さて、エラーメッセージがより分かりやすくなったので、Swift 3で実装された以下の進化案に目を向けてみます。
を述べる[強調]。
を捕捉する
inout
パラメータを を含むself
を含む、変異する メソッド は、エスケープ可能なクロージャリテラルではエラーになります。 になります。 キャプチャが明示されていない限り (そしてそれによって不変)となります。
さて、ここが重要なポイントです。に対して
の値
型(例えば
struct
への呼び出しを所有する型) にも当てはまると思います。
observeSingleEvent(...)
への呼び出しを所有する型にも当てはまると思います。この例では、そのような明示的なキャプチャは可能ではありません。
この問題に対する最も簡単な解決法は
observeSingleEvent(...)
を参照型にすることです。
class
よりも、むしろ
struct
:
class Foo {
init() {}
private func bar(with block: @escaping () -> ()) { block() }
func bax() {
bar { print(self) }
}
}
ただ、この場合
self
を強い参照で捕捉してしまいます。コンテキストによっては (私自身は Firebase を使ったことがないのでわかりませんが)、明示的に
self
を弱く捕捉したいかもしれません。
FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...
関連
-
[解決済み] Xcode 6.3 - 現在の iOS Development 証明書または保留中の証明書要求がすでにあります。
-
[解決済み] キーボードがあるときに、UITextFieldを編集開始時に上に移動させるには?
-
[解決済み] Objective-Cで、ある文字列が他の文字列を含んでいるかどうかを調べるにはどうすればよいですか?
-
[解決済み] iOSのステータスバーの文字色を変更する方法
-
[解決済み] Xcode 7のエラーです。"Missing iOS Distribution signing identity for ..." (iOS配布用署名IDがありません)
-
[解決済み] Swiftではクロージャの内部では常に[unowned self]を使うべきか?
-
[解決済み] CocoaPodsの最新バージョンにアップデートしますか?
-
[解決済み] SwiftでiOSキーボードを任意の場所でタッチして閉じる
-
[解決済み] UITextBorderStyleNoneを使用してUITextFieldのパディングを設定する
-
[解決済み] iOS 11、Apple TV 4Kなどを搭載したXcode 9でワイヤレスデバッグを行う方法とは?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
クラッシュエラー libc++abi.dylib: NSException 型のキャッチできない例外で終了_allanGold のブログ - ProgrammerITS401
-
[解決済み] performSelectorのセレクタが不明なため、リークが発生する可能性があります。
-
[解決済み] SwiftでStringを配列に分割する?
-
[解決済み] Xcodeにおけるバージョンとビルドの比較
-
[解決済み] Unwind segueは何に使うのか、どう使うのか?
-
[解決済み] iPhone 5の画面解像度に対応したアプリを開発・移行するには?
-
[解決済み] SwiftでiOSキーボードを任意の場所でタッチして閉じる
-
[解決済み] iOSで現在のデバイスの言語を取得するには?
-
[解決済み] NSNotificationCenterのaddObserver in Swift
-
[解決済み] UITableView - トップにスクロールする