もっと、いい方法があれば教えてほしいです。
連続する 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
Swift 初心者です。Kotlin からきました。
Apple 公式サンプルコードを3日間 ROM ってました。
どうも納得ができないので書き換えてみました。
動かしてみると3つとも特に問題ないような感じに見えました。
ネットで調べていると、どうもこちらも変化が激しいようで、どの記事を信じたらいいのか分かりません。
コードを見比べながら分からないこと、今後調べたいこと、を洗い出してみます。
ここで必要なのですか。なくても引数は同じ。
init(searchText: Binding<String>, @ViewBuilder content: @escaping (Bird) -> Content) {
パフォーマンス的な何か、なのでしょうか。
_birds = Query(sort: \.creationDate)
すべて、Xcode 任せなのですが、省略できないんです。Bird が。
「Path」というぐらいなのでどこかに通せばいいと思っているのですが。
いきなりでてくる _(アンダースコア)付きのこれ ROM 勢としては驚きました。
どこにもないのにいきなり登場してくる。
どこかに何か隠れてますか。
struct BirdsSearchResults<Content: View>: View {
@Binding var searchText: String
init(searchText: Binding<String>, ...) {
_searchText = searchText
以下すべて挙動が同じに見えます。
struct BirdsSearchResults<Content: View>: View {
@Binding var searchText: String
struct BirdsSearchResults<Content: View>: View {
private var searchText: String
init(searchText: Binding<String>, ...) {
self.searchText = searchText.wrappedValue
struct BirdsSearchResults<Content: View>: View {
private var searchText: Binding<String>
init(searchText: Binding<String>, ...) {
self.searchText = searchText
var body: some View {
let searchText = self.searchText.wrappedValue
ここの部分。
_searchText = searchText
_birds = Query(sort: \.creationDate)
以下記事で勉強したのですが。
👉 SwiftUI Property WrappersクラスのwrappedValue・projectedValue一覧表 #Swift - Qiita
隠しているものを丸出しに露出させることなどできるのでしょうか。

この記述よく見かけます。
birds.filter {
$0.speciesName.contains(
分かりづらい感じがしますが、なぜ具体的なものに置き換えないのでしょうか。
Kotlin でも同様な記述があり、よく怒られていました。
対象の Apple サンプルコードは WWDC2023 のものなので約1年前ぐらいで、そんなに古くはないと思っています。
どうかどうかよろしくおねがいします。
【SwiftUI】@State を 子 View でどう受けるか 🤔 - @Binding #swiftui #swiftdata #プログラミング
👉 https://t.co/Qk0GRimD6K pic.twitter.com/L4QsFIfKlg— chanzmao (@maochanz) December 25, 2023
なぜか、
通常プロジェクトと Playground では Auto-Completion が違う。
マルチなクロージャーを含む
Button(action:label:)
を Auto-Completion で生成して、全クロージャー展開しようとするとできない。
せっかく Playgorund で Completion の使い方を掴んだような気がしてたのに!
【Xcode】自動補完 (Auto Completion) の使い方 - trailing closure#SwiftUI #SwiftData #プログラミング初心者 https://t.co/SkjyyJrFgF
— chanzmao (@maochanz) December 19, 2023
クロージャー展開しようとすると以下の感じ。
Playground 側は OK。
// Playground
Button {
code
} label: {
code
}
// Button(action: <#T##() -> Void#>, label: <#T##() -> View#>)
フォーカスの当たったままコピーすると設定記述的なものがテキストで取得できる。
これが、既存プロジェクト側では、なぜか、展開できない。
// Project
Button(action: {}, label: {
Text("Button")
})
// Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: {
// /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
// })
なんやこれ。
プロジェクト内に同様な記述があると思って探しみたけど見当たらない。
登録されている Completions を
Editor
↓
Show Completions
で確認しても問題はなさそう。

あれこれやっていると、直ることがある。
- Xcode 再起動直後だけ一瞬直る。
- しかし、2回目ぐらいから戻っておかしくなる。
よって、キャッシュか何かを読み込んでいる、と想像。
これでいけた。
rm -rf ~/Library/Developer/Xcode/DerivedData/*
👉 Xcode Quick Fix - Clear Cache
以下でも直ったのかもしれない。
Product
↓
Clean Build Folder...
+
Option

👉 [Xcode][小ネタ] DerivedDataの削除についての備忘録 | DevelopersIO
DerivedData を削除することで効果が出る不具合。
- Build Failed
- ストレージが肥大
- Completion がおかしい
キャッシュのようなもので消しても問題ないらしい。
場所はデフォルトで、
~/Library/Developer/Xcode/DerivedData
で以下メニューから確認できる。
File
↓
{project name} Settings...

少し前に、Xcode をバージョンアップデートしたのでそれが影響しているのかもしれないです。