2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ちょっと危険な@Published

Last updated at Posted at 2020-04-12

Swiftでメモリ安全性が壊れる状況を発見したので、共有

基本的にはSwiftは素晴らしい言語で未初期化の変数というものは存在しません。(明示的にunsafeを使う場合を除く)
classinitで全てのプロパティを初期化する必要があり、変数の確保には初期値が必要です。

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出せばいいのでしょうか?
有識者の方いらっしゃいましたら、お教え願えるとありがたいです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?