#author("2022-11-16T04:34:52+00:00","default:src128","src128")
#author("2022-11-16T05:15:09+00:00","default:src128","src128")
&tag(SwiftUI/PropertyWrapper);
*目次 [#z8da1a17]
#contents
*関連ページ [#n88c2da1]
*参考情報 [#ua83d4c0]

-[[SwiftUIのデータ管理 Property Wrapper編:https://blog.personal-factory.com/2021/01/23/how-to-use-propertywrapper-in-swiftui/]]


*Property Wrapperの種類 [#l9739a89]
-@State、@Binding、@StateObject、@ObservedObjectなどデータを管理するためのProperty Wrapperがたくさん存在する


** @State [#b535e418]
-データが値型。データの更新あり。データの発生源がVIewの場合に使用。
-ボタンをタップするとその数字が増える。
#pre{{
struct StateSample: View {
    private var counter = 0
    var body: some View {
        Button(action: {
            self.counter += 1
        }, label: {
            Text("counter is \(counter)")
        })
    }
}

}}

** @Binding [#pd81fb92]
-データが値型。データの更新あり。データの発生源は外部。
#pre{{
struct ParentView: View {
    @State private var counter = 0
    var body: some View {
        ChildView(counter: $counter)
            .frame(width: .infinity)
    }
}
struct ChildView: View {
    @Binding var counter: Int
    var body: some View {
        Button(action: {
            counter += 1
        }, label: {
            Text("\(counter)")
                .font(.title)
        })
        .border(Color.red)
    }
}
}}

** @Environment [#j1aa4f77]
-Viewの環境値を読み取れるもの。KeyPathを指定する。
#pre{{
struct EnvironmentSample: View {
    @Environment(\.colorScheme) var colorScheme: ColorScheme
    var body: some View {
        if colorScheme == .dark {
            Text("dark mode")
        } else if colorScheme == .light {
            Text("light mode")
        } else {
            Text("")
        }
    }
}
}}

** ObservableObjectプロトコル [#oc30aca6]
-@StateObject、@ObservedObject、@EnvironmentObjectとして使用するデータオブエクトに実装。
#pre{{
class DataSource: ObservableObject {
  @Published var counter = 0
}
}}

** @StateObject [#g4dfa573]
-データが参照型のデータオブジェクト。データの発生源がVIewの場合に使用。
-iOS 14以降。
#pre{{
struct StateObjectSample: View {
    @StateObject private var dataSource = DataSource()
    var body: some View {
        VStack {
            Button("increment counter") {
                dataSource.counter += 1
            }
            Text("StateObject count: \(dataSource.counter)")
                .font(.title)
        }
    }
}
}}

** @ObservedObject [#w79717f5]
-データが他参照のデータオブジェクト。データの発生源が外部。
#pre{{
fileprivate
struct ParentView: View {
    @StateObject private var dataSource = DataSource()
    var body: some View {
        ChildView(dataSource: dataSource)
    }
}

fileprivate
struct ChildView: View {
    @ObservedObject var dataSource: DataSource
    var body: some View {
        VStack {
            Button("increment counter") {
                dataSource.counter += 1
            }
            Text("count: \(dataSource.counter)")
        }
    }
}
}
}

** @StateObjectと@ObservedObjectの違い
-以下のサンプルを考える。
#pre{{
struct StateObjectCounterView: View {
    @StateObject private var dataSource = DataSource()
    var body: some View {
        VStack {
            Button("increment counter") {
                dataSource.counter += 1
            }
            Text("StateObject count: \(dataSource.counter)")
                .font(.title)
        }
    }
}


struct ObservedObjcetCounterView: View {
    @ObservedObject private var dataSource = DataSource()
    var body: some View {
        VStack {
            Button("increment counter") {
                dataSource.counter += 1
            }
            Text("ObservedObject count: \(dataSource.counter)")
                .font(.title)
        }
    }
}


struct SwitchColorView: View {
    @State private var isDanger: Bool = false
    var body: some View {
        VStack {
            Button("Change the Color") {
                isDanger.toggle()
            }
            if isDanger {
                Circle().foregroundColor(.red)
                    .frame(width: 200, height: 200)
            } else {
                Circle().foregroundColor(.green)
                    .frame(width: 200, height: 200)
            }
            StateObjectCounterView()
            ObservedObjcetCounterView()
            Spacer()
        }
    }
}
}}
-StateObjectとObservedObjectをカウントアップした後、「Change the Color」で色を変更すると、StateObjectのカウントは維持されるが、ObservedObjectはリセットされる。
-@StateObjectはViewを表示してから非表示まで。@ObservedObjectはbodyが更新されるまでのため。
-これを避けるためには、@ObservedObjectには親Viewからわたす。

**@EnvironmentObject [#s5554de0]
-参照型オブジェクトを子ビューでアクセスできるようになる。
#pre{{
fileprivate
struct ParentView: View {
    var body: some View {
        ChildView()
    }
}

fileprivate
struct ChildView: View {
    var body: some View {
        GrandChildView()
    }
}

fileprivate
struct GrandChildView: View {
    @EnvironmentObject var dataSource: DataSource
    var body: some View {
        Text("\(dataSource.counter)")
    }
}

struct EnvironmentObjectSample_Previews: PreviewProvider {
    @StateObject static private var dataSource = DataSource()
    static var previews: some View {
        ParentView().environmentObject(dataSource)
    }
}

}}



トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS