SwiftUIのProperty Wrapperをマスターする①〜値型につける〜
こんにちは。ママさんエンジニアのトモヨです。
Swift UIになってからよくつけるようになった@StateなどのProperty Wrapper(プロパティラッパー)の理解度を深めるために勉強しました。
皆様も書いてみるとわかりやすいので実際にコードを書きながら実践してみると面白いです。
実際に書いたコードはこちらです。
下記の記事を参考に学びました。とっても詳しく記載されていてわかりやすかったです。私の記事では気になった部分も含め解説していきます。
https://blog.personal-factory.com/2021/01/23/how-to-use-propertywrapper-in-swiftui/
①単純なプロパティ
まずParentView.swiftというクラスを生成し、自動で入ったテキスト"Hello, World!"を定義してみましょう。
struct ParentView: View {
private let helloWorld = "Hello, World!"
var body: some View {
Text(helloWorld)
}
}
この場合helloWorldはParentViewでしか使用されないのでprivateを。
helloWorldの中身の文字は変更しないのでletを使用しましょう。
②@Stateを使うプロパティ
データが値型
データを更新をする
データの発生源がView自身
の場合は@Stateを使います。画面にボタンがあり、ボタンを押すとカウントが増える画面を作成します。
struct ParentView: View {
@State private var counter = 0
var body: some View {
Button(action: {
counter += 1
}, label: {
Text("counter is \(counter)")
})
}
}
UIKit使用時には@Stateを付与しなくても問題ありませんでしたが、SwiftUIからはエラーが出るようです。
Left side of mutating operator isn't mutable: 'self' is immutable
@Being
値型のデータ
データを更新する
データの発生源は親Viewなど外から渡される場合
に使用します。今回は子Viewに先ほどのconterを渡してみましょう
struct ParentView: View {
@State private var counter = 0
var body: some View {
ChildView(counter: $counter)
}
}
struct ChildView: View {
@Binding var counter: Int
var body: some View {
Button(action: {
counter += 1
}, label: {
Text("\(counter)")
.font(.title)
})
.border(Color.red)
}
}
引き渡されました。ここで確認しておきたいことはChildViewで増やした数は親Viewで定義したcountと同値か?ということです。
確認してみたいので親viewから子viewに画面遷移させてみます。
struct ParentView: View {
@State private var counter = 0
var body: some View {
NavigationView {
VStack{
// 押すと増えるボタン
Button(action: {
counter += 1
}, label: {
Text("\(counter)")
.font(.title)
})
//遷移するボタン
NavigationLink(destination: ChildView(counter: $counter)) {
Text("child Viewへ遷移")
}
}.navigationBarTitle("ParentView", displayMode: .inline)
}
}
}
struct ChildView: View {
@Binding var counter: Int
var body: some View {
// 子viewにもボタンを置く
Button(action: {
counter += 1
}, label: {
Text("\(counter)")
.font(.title)
})
.border(Color.red)
}
}
まずParentViewで3回ボタンを押す
ChildViewに遷移。3が引き継がれていることがわかります。
ChildViewでカウントを増やし5にする
ParentViewに戻ると5になっています。
このことから値は同じものを見ていることがわかります。
@Environment
@State、@Bindingは自分で作ったデータを処理する場合でしたが、
@EnvironmentはViewの環境値を読み取れるProperty Wrapper
こちらで読み込める値が調べられます。
struct EnvironmentSample: View {
@Environment(\.colorScheme) var colorScheme: ColorScheme
var body: some View {
if colorScheme == .dark {
Text("dark mode").foregroundColor(.red)
} else if colorScheme == .light {
Text("light mode").foregroundColor(.red)
} else {
Text("").foregroundColor(.red)
}
}
}
ここまで、値に付随するProperty Wrapperを学習してきました。次回はクラスに付随するProperty Wrapperについて学習します。
この記事が気に入ったらサポートをしてみませんか?