Swiftでメモリ安全性が壊れる状況を発見したので、共有
基本的にはSwiftは素晴らしい言語で未初期化の変数というものは存在しません。(明示的にunsafe
を使う場合を除く)
class
はinit
で全てのプロパティを初期化する必要があり、変数の確保には初期値が必要です。
Swift5.2で導入された@propertyWrapper
によってこの安全性が壊れる場合を見つけたので紹介させていただきます。
具体例
具体的には以下のような状態です。
class Person {
let id = UUID().uuidString
}
class Alice: Person {
@Published var name: String? = nil {
didSet { print(self.id) }
}
override init() {
self.name = "Alice"
super.init()
}
}
let alice = Alice()
本来上記のコードは「何も出力されない」が正解です。
Swiftの仕様では初期化時の代入ではdidSet
は呼ばれないことになっているからです。
しかし、@propertyWrapper
があり、かつ初期値(この場合はnil
)のあるプロパティに関しては、super
が未初期化にもかかわらず、didSet
が呼ばれてしまいます。
このため、上記コードではprint(self.id)
のところで落ちてしまいます。
対策
デフォルト値のあるプロパティはsuper.init()の後に初期化して問題ないはずなので、そのようにする。
感想
早く治ってほしいです。
こういうのってどこにissue
出せばいいのでしょうか?
有識者の方いらっしゃいましたら、お教え願えるとありがたいです。