@State The view owns the data (usually a simple value type like string or double)
@Binding The simple value data (string, float) is passed to the view on construction and creates a two way binding to it
@Published Model classes define these to publish changes to value types
OBJECT TYPES
@StateObject The view owns the model data but this is a full class that implements `ObservableObject`
@ObservedObject The model data is passed to the view on construction. Must implement `ObservableObject`
(our normal case! The same as @Binding with class types)
@EnvironmentObject Same as @Binding (passed in model data implementing ObservableObject),
but comes from a global environment system instead
Example
class MyView: View {
@State var state: String
@Binding var binded: String
@StateObject var model: Model = Model()
init() {
// State
let getState = state // String (same as $state.wrappedValue)
let dollarState = $state // Binding<String>
let underscoreState = _state // State<String>
let dollarStateWrapped = $state.wrappedValue // String
let dollarStateProjected = $state.projectedValue // Binding<String>
// Binded
let dollarBinded = $binded // Binding<String>
let underscoreBinded = _binded // Binding<String>
let getBinded = binded // String (same as $binded.wrappedValue)
let dollarBindedWrapped = $binded.wrappedValue // String
// Model
let getModel = model // Model
let dollarModel = $model // ObservedObject<Model>.Wrapper
let underscoreModel = _model // StateObject<Model>
let getModelPublished = model.published // String
let getModelDollarPublished = model.$published // Published<String>.Publisher
let dollarModelPublished = $model.published // Binding<String>
// let dollarModelUnderscorePublished = $model._published // private / inaccessible
// let dollarModelDollarPublished = $model.$published // Binding<Published<String>.Publisher> (do not use?)
}
}
class Model: ObservableObject {
@Published var published: String
private var cancelSet = Set<AnyCancellable>()
init() {
// Published
let dollarPublished = $published // Published<String>.Publisher
let underscorePublished = _published // Published<String>
let getPublished = published // String
// Debounce model
self.$published
.debounce(for: .seconds(2), scheduler: RunLoop.main)
.sink { [weak self] (newValue) in
print("Debounce published value to newValue: \(newValue)")
}
.store(in: &cancelSet)
}
}