(1) Short Answer (15 points) :
(1) Please distinguish between the following concepts
@state, @Binding, ObservableObject, @observedobject, @environmentobject
This article will teach you how to distinguish between the data state and binding methods commonly used in SwiftUI.
SwiftUI Data status and binding
plan | instructions | note |
---|---|---|
@State & @Binding |
Provides state storage within a View | It should be a simple value type marked private for internal use only. |
ObservableObject & @ObservedObject |
For state sharing across View hierarchies | Handles more complex data types and triggers an interface refresh when data changes. |
@EnvironmentObject |
For states that “jump” across multiple View hierarchies | Make it easier to use ObservableObject to simplify code. |
@State
& @Binding
Parent view:
struct ParentView: View {
@State private var foo: Bool = false
var body: some View {
VStack(spacing: 25) {
Text("foo in Parent: \ [self.foo ? "✔ ️" : "❌")")
ChildView(foo: $foo)}}}Copy the code
Child view:
struct ChildView: View {
@Binding var foo: Bool
var body: some View {
Button("toggle foo from Child") {
self.foo.toggle()
}
}
}
Copy the code
Operation effect:
@ObservedObject
Model:
class Model: ObservableObject {
@Published var foo: Bool = false
}
Copy the code
Notice, @published is internal. In Xcode, the Playground must be public, but in Sources it must be.
import Combine
public class Model: ObservableObject {
public let objectWillChange = PassthroughSubject<Void.Never> ()public var foo: Bool = false {
willSet { objectWillChange.send() }
}
public init(a){}}Copy the code
let objectWillChange = PassthroughSubject<Void, Never>()
Used to implementObservableObject
Agreement;- For every need
@Published
The variablewillSet { objectWillChange.send() }
。
Parent View:
public struct ParentView: View {
@ObservedObject var model: Model = Model(a)public var body: some View {
VStack(spacing: 25) {
Text("foo in Parent: \ [self.model.foo ? "✔ ️" : "❌")")
ChildView(model: model)
}
}
public init(a){}}Copy the code
Child View:
public struct ChildView: View {
var model: Model
public var body: some View {
Button("toggle foo from Child") {
self.model.foo.toggle()
}
}
public init(model: Model) {
self.model = model
}
}
Copy the code
There’s nothing special about using class’s “pass-by-reference” feature to give the child access to the parent model.
@EnvironmentObject
ObservableObject Model:
class Model: ObservableObject {
@Published var foo: Bool = false
}
Copy the code
Parent View:
public struct ParentView: View {
@EnvironmentObject var model: Model
public var body: some View {
VStack(spacing: 25) {
Text("foo in Parent: \ [self.model.foo ? "✔ ️" : "❌")")
ChildView()}}public init(a){}}Copy the code
Child View:
public struct ChildView: View {
@EnvironmentObject var model: Model
public var body: some View {
Button("toggle foo from Child") {
self.model.foo.toggle()
}
}
public init(a){}}Copy the code
Call Parent’s View:
ParentView().environmentObject(Model())
Copy the code
Use EnvironmentObject to give all children access to the parent’s Model to avoid manually passing objects layer by layer.
Complete source code implementation: SwiftUIDataStateAndBinding. Playground.
reference
SwiftUI and Combine Programming Chapter 3: Data State and Binding