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

如何在@Observable标注的类中使用@Resettable属性包装器?

如何同时使用@Resettable属性包装器和@Observable宏?

你遇到的错误确实是因为@Observable宏会将类中的存储属性转换为带合成访问器的计算属性,而属性包装器无法直接应用在计算属性上。下面提供几种可行的解决方案:

方案一:修改@Resettable包装器兼容@Observable

让自定义属性包装器本身遵循Observable协议,内部用@ObservationState管理值的存储,这样@Observable宏就能正确识别并处理它,不会触发冲突:

@propertyWrapper
struct Resettable<T>: Observable {
    @ObservationState private var wrappedValue: T
    let defaultValue: T
    
    init(wrappedValue: T) {
        self.defaultValue = wrappedValue
        self._wrappedValue = ObservationState(wrappedValue)
    }
    
    var wrappedValue: T {
        get { _wrappedValue.wrappedValue }
        set { _wrappedValue.wrappedValue = newValue }
    }
    
    var projectedValue: T { defaultValue }
}

在@Observable类中使用方式保持不变:

@Observable
final class Person {
    @Resettable var name = "John Doe"
    
    func revertName() {
        name = $name
    }
}

这种方案适合有大量需要重置的属性的场景,能复用重置逻辑,同时保留@Observable的观察能力。

方案二:手动维护默认值(无属性包装器)

如果需要重置的属性不多,可以直接在类中存储默认值,去掉属性包装器,手动实现重置逻辑:

@Observable
final class GameScene: SKScene {
    // 存储默认值
    private let defaultRunningSpeed: CGFloat = 1.0
    // 可观察的属性
    var runningSpeed: CGFloat = 1.0
    
    func resetRunningSpeed() {
        runningSpeed = defaultRunningSpeed
    }
}

这种方式简单直接,完全避免了属性包装器和@Observable的冲突,适合属性数量较少的场景。

方案三:手动实现属性访问器

把重置逻辑嵌入到属性的自定义getter/setter中,自己控制存储,同样能兼容@Observable:

@Observable
final class Person {
    private let defaultName = "John Doe"
    private var _name = "John Doe"
    
    var name: String {
        get { _name }
        set { _name = newValue }
    }
    
    func revertName() {
        name = defaultName
    }
}

这种方式完全绕过属性包装器,灵活性高,适合需要对属性访问做额外自定义逻辑的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:24:54