お恥ずかしながら構造体(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がクラスの場合は、このような挙動になりません