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

Swift中get-only下标返回的实例为何无法为其属性赋值?

问题触发原因
  • 你定义的Student是值类型,对值类型属性的赋值本质是对整个值实例的替换。你通过下标返回Student?之后尝试修改其属性,相当于要修改下标返回的值并写回StudentStore的students数组中。
  • 你当前实现的StudentStore下标只有get逻辑,属于只读下标,不支持修改返回值后写回原存储的操作,因此编译器直接抛出报错。
  • 额外补充:数组的first属性本身也是只读的,直接返回它的结果天然不支持修改后同步到原数组。
可行解决方法

方案1:给下标补充setter实现(最推荐,不改动原有数据结构设计)

给下标增加写逻辑,赋值时自动替换数组中对应位置的实例:

class StudentStore {
    var students = [Student]()
    subscript(id: String) -> Student? {
        get {
            students.first(where: { $0.id == id } )
        }
        set {
            // 找到对应索引,用新值替换原有实例
            guard let index = students.firstIndex(where: { $0.id == id }), 
                  let newValue = newValue else { return }
            students[index] = newValue
        }
    }
}

修改完成后原来的赋值代码studentStore["2014901001"]?.attendance = 1可以正常运行。

方案2:将Student改为引用类型(class)

如果你的业务场景适合把Student设计为引用类型,只需要把struct Student改为class Student即可:

class Student {
    var id: String
    var attendance = 0
    var absence = 0
    
    init(id: String) {
        self.id = id
    }
}

此时下标即使是只读的,返回的也是Student实例的引用,修改引用指向对象的属性不需要修改下标返回值本身,不会触发报错。

方案3:直接操作数组索引(无需修改原有封装)

如果不想改动StudentStore和Student的定义,可以直接找到目标元素的索引后修改:

if let index = studentStore.students.firstIndex(where: { $0.id == "2014901001" }) {
    studentStore.students[index].attendance = 1
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:15:03