LoginSignup
7
4

More than 5 years have passed since last update.

Swiftの構造体(struct)のメンバ変数を更新する際の挙動

Posted at

お恥ずかしながら構造体(struct)の挙動を把握できていなかったので備忘録です

プロパティ監視(didSet)を使って、下記のようなコードを書いたりすることってないですか?

struct NameData {
    var firstName: String
    var lastName: String
    var nickName: String
}

class ViewController: UITableViewController {
    var nameData: NameData? {
        didSet {
            tableView.reloadData()
        }
    }

    func fetchData() {
        //通信処理でデータを取得してプロパティに代入
                model.getNameData { [weak self] (data: NameData) in
            self?.nameData = data
        }
    }

}

これは、通信処理から取得したNameData型の値をnameDataプロパティに代入することで、プロパティ監視が走ります
(nameDataプロパティの書き換わりをトリガーとして、tableView.reloadData()を実行するようにしてます)

nameDataを書き換えた後に、わざわざ次の行でtableView.reloadData()を呼ばなくて済むというメリットがあります

先日、このコードに下記のような更新処理を追加しました

//更新処理
func updateNameData() {
    nameData.firstName = "first"
    nameData.lastName = "last"
    nameData.nickName = "nick"
}

その際に同僚に 「これ、updateNameData()メソッド呼んだだけで3回tableView.reloadData()走りません?」 という指摘をもらいました

そんな馬鹿なと思ったのですが、調査してみると構造体のメンバを書き換えただけでもプロパティ監視が走っていました

この挙動を把握しておらず、むやみにtableView.reloadData()を走らせていたということが発覚しました・・

プロパティ監視でtableView.reloadData()だけでなく、他の処理を書いていたら、その処理まで実行させてしまっていたのかと思うと怖くなりました

公式のドキュメントでも、Modifying Value Types from Within Instance Methodsのところに、そのような挙動になるというような感じのこと?が書いてありました

The method can then mutate (that is, change) its properties from within the method, and any changes that it makes are written back to the original structure when the method ends. The method can also assign a completely new instance to its implicit self property, and this new instance will replace the existing one when the method ends.

struct内でmutatingキーワードを使ってメソッドで値を書き換えても同じ挙動になるようです

当然ですが、もちろんNameDataがクラスの場合は、このような挙動になりません

7
4
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
7
4