You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何访问@propertyWrapper的argument参数?

问题描述

现有如下Swift代码:

@propertyWrapper
struct Argument {
    var wrappedValue: Int?
    var argument: String
}

struct Model {
    @Argument var property: Int?
    @Argument(argument: "bar") var foo: Int? = nil
}

extension Model {
    init(property: Int, argument: String = "hello") {
        _property = Argument(wrappedValue: property, argument: argument)
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let model = Model(property: 5)
        print(model)
    }
}

输出结果:

Model(_property: propertyWrapper.Argument(wrappedValue: Optional(5), argument: "hello"), _foo: propertyWrapper.Argument(wrappedValue: nil, argument: "bar"))

可以看到,打印时能访问到@propertyWrapper的argument参数,但model.property和model.foo的类型仅为Int?,无法直接通过model.property.argument获取参数值。想要实现如下效果:

print(model.property.argument) // 打印"hello"
print(model.foo.argument) // 打印"bar"

请问这是否可行?如何实现?


解决方案

方案1:使用Swift默认的投影值(推荐,符合语言设计规范)

Swift的属性包装器默认会生成一个投影值(以$开头),通过这个投影值可以直接访问包装器实例的所有属性,无需修改原有代码结构:

let model = Model(property: 5)
print(model.$property.argument) // 输出"hello"
print(model.$foo.argument) // 输出"bar"

这种方式是Swift官方推荐的访问属性包装器内部属性的方式,简洁且符合语言规范。

方案2:修改包装器,让wrappedValue返回包含值和参数的自定义类型

如果一定要实现model.property.argument的写法,可以调整Argument包装器的设计,让wrappedValue返回一个同时包含可选整数和argument属性的自定义类型,同时支持隐式转换为Int?,保证原有用法不变:

@propertyWrapper
struct Argument {
    private var value: Int?
    let argument: String
    
    var wrappedValue: WrappedValue {
        WrappedValue(value: value, argument: argument)
    }
    
    // 自定义包装值类型
    struct WrappedValue {
        let value: Int?
        let argument: String
        
        // 支持直接当作Int?使用
        var intValue: Int? { value }
    }
    
    // 初始化方法适配原有代码
    init(wrappedValue: Int?, argument: String = "") {
        self.value = wrappedValue
        self.argument = argument
    }
    
    init(argument: String) {
        self.value = nil
        self.argument = argument
    }
}

// 调整Model的属性类型
struct Model {
    @Argument var property: Argument.WrappedValue
    @Argument(argument: "bar") var foo: Argument.WrappedValue = Argument.WrappedValue(value: nil, argument: "bar")
}

extension Model {
    init(property: Int, argument: String = "hello") {
        _property = Argument(wrappedValue: property, argument: argument)
    }
}

// 使用示例
let model = Model(property: 5)
print(model.property.argument) // 输出"hello"
print(model.foo.argument) // 输出"bar"
// 依然可以获取原始Int?值
if let propertyValue = model.property.intValue {
    print("Property value: \(propertyValue)") // 输出"Property value: 5"
}

这种方式虽然实现了需求,但会增加代码复杂度,偏离Swift属性包装器的常规用法,建议优先使用方案1。


内容的提问来源于stack exchange,提问作者Makalele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:03:31