Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synthesised init for a struct with @propertyWrapper members

What's the magic attached to SwiftUI's @State property wrapper which means I can I do this?:

struct A {    
    @State var s: String
}

let a = A(s: "string") //uses a synthesised init for `A` which allows me to init A with the underlying type of `A.s` - a `string`

whereas if I roll my own @propertyWrapper, I can't?

@propertyWrapper
struct Prop<Value> {
    var value: Value
    var wrappedValue: Value {
        get { value }
        set { value = newValue }
    }
}

struct B {
    @Prop var s: String
}

let b = B(s: "string") // Compiler error: `Cannot convert value of type 'String' to expected argument type 'Prop<String>'`
let b = B(s: Prop(value: "string")) // Works, but is ugly
like image 525
sam-w Avatar asked Oct 20 '25 12:10

sam-w


1 Answers

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
}
like image 198
sam-w Avatar answered Oct 23 '25 08:10

sam-w



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!