もっと、いい方法があれば教えてほしいです。
連続する Modifirer の中で
パディング、マージンの調整に便利かも、
という発想。
視覚的に把握できるの便利。
View Debugger で見るより実はシンプルで速い。
慣れてしまえばどうでもいい話かな。
もっと、いい方法があれば教えてほしいです。
連続する Modifirer の中で
パディング、マージンの調整に便利かも、
という発想。
視覚的に把握できるの便利。
View Debugger で見るより実はシンプルで速い。
慣れてしまえばどうでもいい話かな。
これ、みんなフツーに書いてるけど。
これだけ。
struct ToggleView: View {
@State var isOn = true
var body: some View {
Toggle(isOn ? "ON" : "OFF", isOn: $isOn)
}
}
スゴイよね、SwiftUI。
これよ。
@State var isOn = true
プロパティの記述をざっくり考えると、
[@State] [public|private] {let|var} isOn[: Bool] [= true]
となり、数十通りあるのに!
いくつか書き出して試してみます。
let isOn: Bool
let isOn: Bool = true
var isOn: Bool
var isOn: Bool = true
private let isOn: Bool
private let isOn: Bool = true
private var isOn: Bool
private var isOn: Bool = true
@State let isOn: Bool
@State let isOn: Bool = true
@State var isOn: Bool
@State var isOn: Bool = true
@State private let isOn: Bool
@State private let isOn: Bool = true
@State private var isOn: Bool
@State private var isOn: Bool = true
// Cannot find '$isOn' in scope
let isOn: Bool
let isOn: Bool = true
var isOn: Bool
var isOn: Bool = true
private let isOn: Bool
private let isOn: Bool = true
private var isOn: Bool
private var isOn: Bool = true
→ Toggle() の2番目の引数 $isOn が見つからない。
// Property wrapper can only be applied to a 'var'
@State let isOn: Bool
@State let isOn: Bool = true
@State private let isOn: Bool
@State private let isOn: Bool = true
→ @State には var しか使えない。
// Missing argument for parameter 'isOn' in call
@State var isOn: Bool
→ isOn の中身がない。
// Missing argument for parameter 'isOn' in call
// 'ToggleView' initializer is inaccessible due to 'private' protection level
@State private var isOn: Bool
→ isOn の中身がない。
→ private なのでイニシャライザーがアクセスできません。
// OK
@State var isOn: Bool = true
@State private var isOn: Bool = true
→ OK
Property wrapper は var 。
中身が変わるからかな。
【SwiftUI】@State を 子 View でどう受けるか 🤔 - @Binding #swiftui #swiftdata #プログラミング
👉 https://t.co/Qk0GRimD6K pic.twitter.com/L4QsFIfKlg— chanzmao (@maochanz) December 25, 2023
SwiftUI を使うには基本で必須です。
@State と @Binding。
どう書いてますか。
親 View があるとして 子 View でどう受けるか。
struct ParentView: View {
@State private var text: String = ""
var body: some View {
VStack {
TextField("Parent", text: $text)
Text(text)
Divider()
ChildView(text: $text)
}
.padding()
}
}
struct ChildView: View {
var body: some View {
TextField()
Text()
}
}
こういうイメージです。
きちんと Binding されていますね。
ChildView をシンプルに書いてみます。
あくまで受け渡し記述の確認です。
他言語からきて、まずは書きそうなこれ。
イニシャライザ経由で型を合わせて渡します。
wrappedValue も直感的に分かるでしょう。
struct ChildView: View {
private var text: Binding<String>
init(text: Binding<String>) {
self.text = text
}
var body: some View {
TextField("Child", text: text)
Text(text.wrappedValue)
}
}
→ OK
次は、イニシャライザーを使わずに、プロパティを露出させます。
struct ChildView: View {
var text: Binding<String>
var body: some View {
TextField("Child", text: text)
Text(text.wrappedValue)
}
}
→ OK
次は、マクロを使います。
@State で受けると、参照が切れます。新規に作成するんですね。
struct ChildView: View {
@State private var text: String
init(text: Binding<String>) {
self.text = text.wrappedValue
}
var body: some View {
TextField("Child", text: $text)
Text(text)
}
}
→ NG
次は、何も分かってないのに @Binding を使います。
struct ChildView: View {
@Binding private var text: String
init(text: Binding<String>) {
self.text.projectedValue = text // NG
}
var body: some View {
TextField("Child", text: $text)
Text(text)
}
}
Referencing property 'projectedValue' requires wrapper 'Binding<String>'
→ NG
次は、少しネットで調べて、一番多く目についた書き方。
_ (アンダースコア) が強烈な違和感ですが、問題なく動きます。
struct ChildView: View {
@Binding private var text: String
init(text: Binding<String>) {
_text = text
}
var body: some View {
TextField("Child", text: $text)
Text(text)
}
}
→ OK
次は、public にして、イニシャライザー省略。
struct ChildView: View {
@Binding var text: String
var body: some View {
TextField("Child", text: $text)
Text(text)
}
}
→ OK
これが一番簡潔に書けるんですね!
struct ChildView: View {
@Binding var text: String
var body: some View {
TextField("Child", text: $text)
Text(text)
}
}
子ではプロパティのアクセス修飾子を public のイニシャライザー省略で受ける。
どうやら、この
@Binding var text: String
は、
private var _text: Binding<String>
private var text: String {
get {
_text.wrappedValue
}
set {
_text.wrappedValue = newValue
}
}
init(text: Binding<String>) {
_text = text
}
と等価のようにみえます。
あと、孫 View に渡すには、@Binding から @Binding できますね!
※ 後で知ったのですが、public や private などのアクセスレベルの省略は「internal」扱いでした !
最後に、Playground コードを貼っておきます。
Jetpack Compose から SwiftUI に来ましたが今の謎をどうにかしたい 😩#jetpackcompose #swiftui #プログラミング初心者 https://t.co/Ojrd7C1rWq
— chanzmao (@maochanz) December 21, 2023