概要
を視聴していたら,36:31ぐらいからちょうどタイトルと同じような内容が紹介されていた。パッと理解することができなかったので,まとめてみます。
実例
以下の例を見てみる。
import SwiftUI
struct ContentView: View {
@State private var isOpacity: Bool = false
var body: some View {
VStack {
if isOpacity {
ChildView()
.opacity(0.3)
} else {
ChildView()
}
Button("Change Opacity") {
isOpacity.toggle()
}
}
}
}
struct ChildView: View {
@State private var isGood: Bool = false
var body: some View {
VStack {
Text(isGood ? "Good" : "Bad")
Button("Change Goodness") {
isGood.toggle()
}
}
}
}
ContentView
ではopacityを変化させるisOpacity
を管理しており,ChildView
では文言"Good"/"Bad"
を変化させるisGood
を管理している。ContentView
では,opacityを変化させるためにif文を使用している。一見問題なさそうに見えるが,挙動を確かめてみる。
挙動が以下のようになっている。
- "Change Goodness"ボタンを押して,テキストを"Bad"から"Good"に変更した
- "Change Opacity"ボタンを押して,opacityを0.3に変更した
- 2でopacityのみ変更したが,テキストも"Good"から"Bad"に変更されている
原因
が非常に参考になった。
SwiftUI destroys and creates the views whenever the condition changes. This process deallocates the destroyed view’s state and uses animation to remove the destroyed view.
より,ContentView
のisOpacity
が変わった時,ChildView
が再生成されisGood
がデフォルトのfalseとなり,opacityだけではなく,文言も"Good"から"Bad"に変わってしまった。
解決方法
struct ContentView: View {
@State private var isOpacity: Bool = false
var body: some View {
VStack {
ChildView()
.opacity(isOpacity ? 0.3 : 1)
Button("Change Opacity") {
isOpacity.toggle()
}
}
}
}
上記のように,opacity
で指定する値自体をisOpacity
で出し分ければ良い。
There is no changes in the view tree when you set the padding to 0 or opacity to 1. SwiftUI understands that and doesn’t apply these view modifiers. That’s why we call them inert view modifiers. Try to use them as much as possible to improve the performance of your view and remove unwanted transitions.
とあるように,opacity
で1を指定してもmodifierが適用されないそう。ちなみに inert = 不活性 だそう。