RxSwift で VM 作るとき Structure だと厳しいやつ

RxSwift で VM 作ろうとすると、

import RxSwift
import Firebase
struct EbisuViewModel {

var weatherVariable = Variable<>("")

mutating func data() {

let ref = Database.database().reference()
ref.
observe(of: .value, with: { [weak self] snapshot in
self.weatherVariable.value = //...snapshot....
}
}
// ...
}

ってしたくなりますよねえ。でももちろん

Closure cannot implicitly capture a mutating self parameter

とか

‘weak’ may only be applied to class and class-bound protocol types, not ‘EbisuViewModel’

って怒られちゃうわけです。

なんだかよくわかんないまま諦めていたので、理由を考えてみました。

  • Class はリファレンスを複数作れます。リファレンスはスタック、本体はヒープに入ってます(たぶん)。ある一個のリファレンスがスコープから抜けて死んでも、他のリファレンスが生きていれば本体は死にません。
  • Structure はリファレンス1個限定です。本体どこに入ってるのかわかんないですが、リファレンスがスコープを抜けて死んだら、本体も死にます。

Structure の中のクロージャに self 渡そうとしても、クロージャは絶対ヒープに入ってるから……あ、どうやっても無理そうですね。

例えば @escaping とか inout とかそういうのを持ち出しても、最後戻すときに Structure さんの本体こと self がいなくなってるんじゃ、クロージャさんはわけのわからない副作用を起こすくらいしかやることがないです。

調べていると Structure 使えるときは使いなよ、というのが公式の見解だし、確かにメモリのことをあんまり気にしなくていいから使いたいけど、 RxSwift / VM / 外の世界の組み合わせでは、 Class を使うことになりそうです。

あとで見る

https://developer.apple.com/videos/play/wwdc2015/408/

https://developer.apple.com/videos/play/wwdc2015/414/

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.