非常棒的问题!你说的这三个:
• _属性名
• $属性名
• 属性名
确实是 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 实例(结构体)