Skip to content

Instantly share code, notes, and snippets.

@yimajo
Last active September 6, 2021 09:21
Show Gist options
  • Save yimajo/d34a6a33c7369512bd0d67b058187846 to your computer and use it in GitHub Desktop.
Save yimajo/d34a6a33c7369512bd0d67b058187846 to your computer and use it in GitHub Desktop.
SwiftUIでBindingは参照元の値を変更できるが、Stateは参照元の値を変更できないサンプル。Playgroundで動作する。
import PlaygroundSupport
import SwiftUI
import Combine
class ObservableObject1: ObservableObject {
@Published var name: String = "src"
}
struct ContentView1: View {
@ObservedObject private var object = ObservableObject1()
var body: some View {
VStack {
VStack {
Text("Change from: \(object.name)")
}
VStack {
Text("ContentView @ObservableObject")
.font(.headline)
Button(action: {
self.object.name = "ContentView1"
}) {
Text("ContentView: Button \(object.name)")
}
}
.padding(20)
VStack {
Text("SubViewO @ObservedObject")
.font(.headline)
SubViewO(object: object)
}
.padding(20)
VStack {
Text("SubViewB @Binding")
.font(.headline)
SubViewB(name: self.$object.name)
}
.padding(20)
VStack {
Text("SubViewS @State")
.font(.headline)
SubViewS(name: self.object.name)
}
}
}
}
struct SubViewO: View {
@ObservedObject private(set) var object: ObservableObject1
var body: some View {
VStack {
Button(action: {
self.object.name = "SubViewO!!"
}) {
Text("SubViewO: Button \(object.name)")
}
}
}
}
struct SubViewB: View {
// Viewがデータに対してBindingする。
// 双方向(two-way)のBindingとなり、このViewで変更されたら参照元も変更する。
// https://developer.apple.com/documentation/swiftui/binding
@Binding private(set) var name: String
var body: some View {
VStack {
Button(action: {
// 参照元のnameも変更できる
// 参照元はObservableObjectなのでそのnameも変わる
self.name = "SubViewB!!"
}) {
Text("SubViewB: Button \(self.name)")
}
}
}
}
struct SubViewS: View {
// Viewがデータにconnectされる。
// 参照元からは初期値のみ取得し参照元の監視はしていない。
// Viewはデータを保持し、View内でデータが更新されるとViewを更新する。
// https://developer.apple.com/documentation/swiftui/state
// 外側から変更されるべきではないのでprivateに。
// privateにするとinit書かないといけないの面倒なのでprivate(set)にした。
@State private(set) var name: String
var body: some View {
VStack {
Button(action: {
// 自分のStateを変えるが参照元は変わらない
self.name = "SubviewS!!"
}) {
Text("SubViewS: Button \(self.name)")
}
.padding(10)
SubViewS_B(name: self.$name)
}
}
}
struct SubViewS_B: View {
@Binding private(set) var name: String
var body: some View {
VStack {
Text("SubViewS_B @State-@Bind")
.font(.headline)
Button(action: {
// 参照元ののnameも変更する
// 参照元がStateならそれ以上(ObservableObjectの値)は変わらない
self.name = "SubviewS_B!!"
}) {
Text("SubViewS_B: Button \(self.name)")
}
}
}
}
PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView1())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment