带有 @propertyWrapper 成员的结构体的综合 init

sam*_*m-w 4 swift swift5 swiftui

SwiftUI 的属性包装器有什么魔力,@State这意味着我可以做到这一点?:

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`
Run Code Online (Sandbox Code Playgroud)

而如果我自己推出@propertyWrapper,我就不能?

@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
Run Code Online (Sandbox Code Playgroud)

sam*_*m-w 5

如记录于:

...您可以让编译器为您执行此操作,就像它所做的那样- 只需在属性包装器定义中@State添加特定的魔法即可:init(wrappedValue:)

@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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这还允许您在结构定义中为包装属性分配默认值:

struct B {
    @Prop var s: String = "default value" // Works now; would have thrown a compiler error before
}
Run Code Online (Sandbox Code Playgroud)