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

如何让自定义Between1and4属性包装器支持@Published?

问题描述

我有一个用于将变量值限制在1到4之间的@propertyWrapper结构体Between1and4,代码如下:

@propertyWrapper
struct Between1and4 {
  internal static let lowest = CGFloat(1.0)
  internal static let highest = CGFloat(4.0)
  private var value: CGFloat
  var wrappedValue: CGFloat {
    get { return value }
    set { value = CGFloat(min(max(Between1and4.lowest, newValue), Between1and4.highest))
    }
  }
  
  init(wrappedValue: CGFloat) {
    self.value = wrappedValue
  }
}

现在想在ObservableObject类中创建一个带@Published的属性,要求该属性使用Between1and4的范围限制特性。尝试使用@Published @Between1and4 var scale: CGFloat时,出现以下错误:

Arguments to generic parameter 'Value' ('CGFloat' and 'Between1and4') are expected to be equal.

Cannot convert value of type 'ReferenceWritableKeyPath<ContentViewModel, CGFloat>' to expected argument type 'ReferenceWritableKeyPath<ContentViewModel, Between1and4>'
解决方案

方法一:计算属性配合私有@Published属性

这种方法无需叠加属性包装器,通过私有发布属性+公开计算属性实现范围限制和更新发布,逻辑清晰易维护:

final class ContentViewModel: ObservableObject {
    // 私有@Published属性存储实际值
    @Published private var _scale: CGFloat = 1.0
    
    // 公开计算属性,自动应用范围限制
    var scale: CGFloat {
        get { _scale }
        set {
            _scale = min(max(Between1and4.lowest, newValue), Between1and4.highest)
        }
    }
}

使用时直接访问viewModel.scale即可,既会自动将值限制在1-4之间,又能触发ObservableObject的更新发布。

方法二:调整属性包装器的使用方式

如果坚持使用自定义属性包装器,可以将属性类型声明为Between1and4,让@Published直接包装该属性包装器实例,同时提供便捷访问的计算属性:

final class ContentViewModel: ObservableObject {
    @Published var scaleWrapper = Between1and4(wrappedValue: 1.0)
    
    // 便捷访问包装后的实际值
    var scale: CGFloat {
        get { scaleWrapper.wrappedValue }
        set { scaleWrapper.wrappedValue = newValue }
    }
}

错误原因说明

之前的写法报错是因为属性包装器叠加顺序导致类型不匹配:

  • @Between1and4会把CGFloat包装成Between1and4实例
  • @Published会尝试包装这个Between1and4实例,此时它的泛型参数是Between1and4,但你声明的属性类型是CGFloat,两者不匹配,因此抛出错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 03:42:25