Difference between @propertyDelegate and @propertyWrapper
TLDR; they are the same but you should use @propertyWrapper
.
As pointed out by @JosefDolezal on twitter https://twitter.com/josefdolezal/status/1137619597002248192?s=21, the name @propertyDelegate
was returned for revision by the core team https://forums.swift.org/t/returned-for-revision-se-0258-property-delegates/24080. The core team proposed multiple alternative namings, but because the proposal wasnt finalized before WWDC, they chose one of them to introduce this feature to the world.
So its very likely that @propertyDelegate
will be removed, and likely that @propertyWrapper
will stay, although this could still change during the ongoing evolution process.
Synthesised init for a struct with @propertyWrapper members
As documented in:
- Swift evolution proposals
- Deep in the language guide
... you can get the compiler to do this for you, as it does with @State
- just add a specific magic init(wrappedValue:)
to your property wrapper definition:
@propertyWrapper
struct Prop<Value> {
var value: Value
var wrappedValue: Value {
get { value }
set { value = newValue }
}
// magic sauce
init(wrappedValue: Value) {
self.value = wrappedValue
}
}
struct B {
@Prop var s: String
}
let b = B(s: "string") // Now works
Incidentally, this also allows you to assign default values for your wrapped properties in the struct definition:
struct B {
@Prop var s: String = "default value" // Works now; would have thrown a compiler error before
}
What does the SwiftUI `@State` keyword do?
The @State
keyword is a @propertyWrapper
, a feature just recently introduced in Swift 5.1. As explained in the corresponding proposal, it's sort of a value wrapper avoiding boilerplate code.
Sidenote: @propertyWrapper
has previously been called @propertyDelegate
, but that has changed since. See this post for more information.
The official @State documentation has the following to say:
SwiftUI
manages the storage of any property you declare as a state.
When the state value changes, the view invalidates its appearance and
recomputes the body. Use the state as the single source of truth for a
given view.A State instance isn’t the value itself; it’s a means of
reading and mutating the value. To access a state’s underlying value,
use its value property.
So when you initialize a property that's marked @State
, you're not actually creating your own variable, but rather prompting SwiftUI
to create "something" in the background that stores what you set and monitors it from now on! Your @State var
just acts as a delegate to access this wrapper.
Every time your @State
variable is written, SwiftUI
will know as it is monitoring it. It will also know whether the @State
variable was read from the View
's body
. Using this information, it will be able to recompute any View
having referenced a @State
variable in its body
after a change to this variable.
Can a Swift Property Wrapper reference the owner of the property its wrapping?
The answer is no, it's not possible with the current specification.
I wanted to do something similar. The best I could come up with was to use reflection in a function at the end of init(...)
. At least this way you can annotate your types and only add a single function call in init()
.
fileprivate protocol BindableObjectPropertySettable {
var didSet: () -> Void { get set }
}
@propertyDelegate
class BindableObjectProperty<T>: BindableObjectPropertySettable {
var value: T {
didSet {
self.didSet()
}
}
var didSet: () -> Void = { }
init(initialValue: T) {
self.value = initialValue
}
}
extension BindableObject {
// Call this at the end of init() after calling super
func bindProperties(_ didSet: @escaping () -> Void) {
let mirror = Mirror(reflecting: self)
for child in mirror.children {
if var child = child.value as? BindableObjectPropertySettable {
child.didSet = didSet
}
}
}
}
Related Topics
Swift Can Change Struct Declared with Let If Using an Index But Not If Using a Loop
Scenekit - Why Scnlight Created Automatically in Scnscene
How to Find The Nth Root of a Value
How to Invoke Method with Cvalistpointer Parameters in Swift
Uimarkuptextprintformatter and MAC Catalyst
Xcodebuild Commands Failed to Generate Ipa
Swift iOS14 Datepicker Text Alignment
Swift Navigation Bar Item Not Calling Action
Reachability Change Notification Should Be Called Only Once
Cell Is Duplicated Multiple Times When Posting to Firebase
Iterating Through an Array of Strings, Fetched from Mongodb
Different UIfont Sizes for Different iOS Devices in Swift
How to Add Two Generic Values in Swift
Swift Making Copies of Passed Class Instances
Swift Selector with Default Argument
Swift Short Syntax of Execution
Calling Git Commands from Within a Swift Macos Application
Create an Array of Protocols with Constrained Associated Types