属性包装器中的三种不同属性名

96 阅读1分钟

非常棒的问题!你说的这三个:

• _属性名

• $属性名

• 属性名

确实是 Swift 属性包装器(@propertyWrapper)内部的三个不同访问层次,我们来逐个解释 👇

🟢 1. 属性名(就是我们平常访问的名字)

@Validation var name: String

你访问 name 时,其实访问的是:

_属性名.wrappedValue

也就是:

✅ name == _name.wrappedValue

🟡 2. $属性名(投影值,projectedValue)

你访问 $name,就是访问包装器中的 projectedValue:

$name == _name.projectedValue

这个是你在包装器里自定义的,比如:

var projectedValue: Bool {
    wrappedValue == defaultValue
}

这个值可以是任何类型,比如 Bool、Binding、甚至一个结构体。

🔵 3. _属性名(底层包装器实例)

这个是编译器生成的“隐藏变量”,其实就是整个包装器的实例,你可以直接访问它:

_属性名.wrappedValue
_属性名.projectedValue

比如:你在 init() 中自己赋值时,就会用到 _属性名 = ...

📦 总结一张表:

写法

实际含义

示例

属性名

访问 wrappedValue

name → _name.wrappedValue

$属性名

访问 projectedValue

$name → _name.projectedValue

_属性名

包装器的实例本身

你能用它手动设置属性包装器

✅ 示例完整代码

@propertyWrapper
struct Validation {
    private var value: String
    var wrappedValue: String {
        get { value }
        set { value = newValue }
    }
    var projectedValue: Bool {
        value.isEmpty
    }
    init(wrappedValue: String) {
        self.value = wrappedValue
    }
}

struct User {
    @Validation var name: String = ""
}

let user = User()
print(user.name)   // name
print(user.$name)  // Bool → projectedValue
print(user._name)  // Validation 实例(结构体)