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

SwiftUI Stepper直接绑定Sire模型属性时无法正常工作

问题解决:Stepper绑定结构体属性后仅能变更一次的问题

问题根源

你自定义的Sire结构体实现了Equatable协议,但==方法只比较了id、name和ownerID,未包含cars、cups等其他属性。当通过Stepper修改newSire.cars时,生成的新Sire实例与旧实例通过自定义==判断会被认定为相等,这会干扰SwiftUI的状态更新机制——SwiftUI会误以为状态未发生变化,进而导致Stepper绑定失效,表现为仅能点击一次后进入禁用状态。

解决方案

有两种可行的修复方式:

方式1:更新Equatable实现,覆盖所有属性

修改Sire的==方法和hash(into:)方法,将所有属性纳入相等性判断和哈希计算:

struct Sire: Hashable, Identifiable, Decodable  {
    static func == (lhs: Sire, rhs: Sire) -> Bool {
        lhs.id == rhs.id &&
        lhs.name == rhs.name &&
        lhs.ownerID == rhs.ownerID &&
        lhs.fatherID == rhs.fatherID &&
        lhs.info == rhs.info &&
        lhs.achievments == rhs.achievments &&
        lhs.cars == rhs.cars &&
        lhs.cups == rhs.cups
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(name)
        hasher.combine(ownerID)
        hasher.combine(fatherID)
        hasher.combine(info)
        hasher.combine(achievments)
        hasher.combine(cars)
        hasher.combine(cups)
    }
    
    // 其余属性和初始化方法保持不变
     var id:String
     var name:String
     var ownerID:Int
     var fatherID:String?
     var info:String?
     var achievments:String?
     var cars:Int = 0
     var cups:Int = 0
    
     
    init (id:String, name:String, ownerID:Int, info:String? = nil, achievments:String? = nil,
          fatherID:String? = nil, cars:Int = 0, cups:Int = 0) {
         self.id = id
         self.name = name
         self.ownerID = ownerID
         self.cars = cars
         self.cups = cups
        self.info = info
        self.achievments = achievments
     }  
}

方式2:移除自定义的Equatable和Hashable实现

如果业务逻辑不需要自定义相等性判断,可直接删除自定义的==方法和hash(into:)方法。Swift会自动为所有属性符合Equatable/Hashable协议的结构体生成默认实现,确保正确识别所有属性的变化:

struct Sire: Hashable, Identifiable, Decodable  {
     var id:String
     var name:String
     var ownerID:Int
     var fatherID:String?
     var info:String?
     var achievments:String?
     var cars:Int = 0
     var cups:Int = 0
    
     
    init (id:String, name:String, ownerID:Int, info:String? = nil, achievments:String? = nil,
          fatherID:String? = nil, cars:Int = 0, cups:Int = 0) {
         self.id = id
         self.name = name
         self.ownerID = ownerID
         self.cars = cars
         self.cups = cups
        self.info = info
        self.achievments = achievments
     }  
}

验证修改

修改完成后重新运行项目,Stepper绑定$newSire.cars即可正常响应每次点击,不会再出现点击一次就禁用的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:45:44