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

修改关联枚举的entry值报错:无法赋值给不可变String表达式

问题原因分析

你遇到的错误“Cannot assign to immutable expression of type 'String'”本质上有两个核心原因:

  1. 元组是值类型:TextFieldInfo是一个元组,当你访问TextFieldModelEnum的info计算属性时,返回的是元组的副本,而不是指向原枚举关联值的引用——你修改这个副本的entry值,既不会影响原枚举实例,编译器也会因为临时值不可变而报错。
  2. 枚举关联值默认不可变:Swift枚举的关联值是通过let绑定的,你无法直接修改枚举case里的关联值内容,必须重新创建枚举实例来覆盖原有的值。

解决方案

下面提供两种可行的修复方案,你可以根据自己的业务需求选择:

方案一:给枚举添加可变方法更新entry

我们可以给TextFieldModelEnum添加一个mutating方法,通过重新创建枚举实例来更新entry值:

public enum TextFieldModelEnum {
    case generic(type: TextFieldType, title: String)
    case entry(type: TextFieldType, title: String, entry: String)
    
    var info: TextFieldInfo {
        switch self {
        case .generic(let type, let title):
            return (type, title, "")
        case .entry(let type, let title, let entry):
            return (type, title, entry)
        }
    }
    
    // 添加mutating方法,用于更新entry值
    mutating func updateEntry(_ newEntry: String) {
        switch self {
        case .generic(let type, let title):
            // 如果是generic类型,可选择转换为entry类型(根据你的业务逻辑调整)
            self = .entry(type: type, title: title, entry: newEntry)
        case .entry(let type, let title, _):
            // 重新创建entry case,替换原有entry值
            self = .entry(type: type, title: title, entry: newEntry)
        }
    }
}

然后在你的代理方法中调用这个方法即可:

extension ThirdViewController: TextProtocol {
    func getText(text: String) {
        // 调用updateEntry修改entry值
        self.array[self.rowListSelected].updateEntry(text)
        let indexPaths = [IndexPath(row: self.rowListSelected, section: 0)]
        self.tableView.reloadRows(at: indexPaths, with: .none)
        print(text)
    }
}

方案二:将枚举改为结构体(更推荐的方案)

如果你的TextFieldModelEnum的两个case本质上是同一类模型的不同状态,使用结构体会更灵活,因为结构体的属性可以直接声明为可变:

public struct TextFieldModel {
    let type: TextFieldType
    let title: String
    var entry: String // 用var声明,允许直接修改
    
    // 对应原枚举的generic case
    init(type: TextFieldType, title: String) {
        self.type = type
        self.title = title
        self.entry = ""
    }
    
    // 对应原枚举的entry case
    init(type: TextFieldType, title: String, entry: String) {
        self.type = type
        self.title = title
        self.entry = entry
    }
    
    // 保留原有的info属性(如果需要兼容旧代码)
    var info: TextFieldInfo {
        return (type, title, entry)
    }
}

此时你的代理方法可以直接修改entry属性:

extension ThirdViewController: TextProtocol {
    func getText(text: String) {
        self.array[self.rowListSelected].entry = text
        let indexPaths = [IndexPath(row: self.rowListSelected, section: 0)]
        self.tableView.reloadRows(at: indexPaths, with: .none)
        print(text)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:37:40