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

SwiftUI报错:Cannot use mutating member on immutable value,如何修复?

错误翻译

无法对不可变值使用可变成员:'self'是不可变的

问题原因

questions是QuizView结构体的普通存储属性,而结构体属于值类型,默认情况下结构体实例的属性是不可变的。shuffle()是数组的可变方法——它会直接修改调用它的数组本身,所以在onAppear的闭包中尝试修改不可变的questions属性,就会触发这个错误。

解决方案

这里提供两种直接有效的修复方式:

方法1:将questions标记为@State属性

通过@State让SwiftUI管理属性的可变性,允许在闭包中修改它:

struct QuizView: View {
    // 将questions改为@State属性
    @State var questions = [("What is the capital of France?", ["Paris", "London", "New York", "San Francisco"], "Paris"),
                     ("What is the capital of Italy?", ["Rome", "Paris", "Madrid", "Berlin"], "Rome"),
                     ("What is the capital of Spain?", ["Barcelona", "Madrid", "Rome", "Paris"], "Madrid"),
                     ("What is the capital of Germany?", ["Berlin", "Paris", "London", "New York"], "Berlin"),
                     ("What is the capital of the UK?", ["London", "Paris", "Madrid", "New York"], "London"),
    ]

    @State var currentQuestion = 0
    @State var score1 = 0
    @State var remainingQuestions = [Int]()
    
    var body: some View {
        VStack {
            // 示例:显示当前题目
            Text(questions[currentQuestion].0)
            // 此处补充你的选项视图、交互逻辑等
        }.onAppear {
            questions.shuffle()
            remainingQuestions = Array(0..<questions.count)
        }
    }
}

方法2:初始化时完成洗牌

如果不想将questions设为@State,可以在结构体初始化阶段创建可变副本并洗牌,避免在视图生命周期中修改不可变属性:

struct QuizView: View {
    var questions: [(String, [String], String)]
    
    @State var currentQuestion = 0
    @State var score1 = 0
    @State var remainingQuestions = [Int]()
    
    init() {
        // 创建临时可变数组并洗牌
        var tempQuestions = [("What is the capital of France?", ["Paris", "London", "New York", "San Francisco"], "Paris"),
                     ("What is the capital of Italy?", ["Rome", "Paris", "Madrid", "Berlin"], "Rome"),
                     ("What is the capital of Spain?", ["Barcelona", "Madrid", "Rome", "Paris"], "Madrid"),
                     ("What is the capital of Germany?", ["Berlin", "Paris", "London", "New York"], "Berlin"),
                     ("What is the capital of the UK?", ["London", "Paris", "Madrid", "New York"], "London"),
        ]
        tempQuestions.shuffle()
        self.questions = tempQuestions
    }
    
    var body: some View {
        VStack {
            Text(questions[currentQuestion].0)
            // 此处补充你的选项视图、交互逻辑等
        }.onAppear {
            remainingQuestions = Array(0..<questions.count)
        }
    }
}
额外提示

如果题目数据是从外部传入的(比如父视图传递),可以将questions改为@Binding类型,或者在父视图中先完成洗牌再传入;另外,shuffled()方法(注意不是shuffle())会返回一个洗牌后的新数组,不会修改原数组,适合不需要保留原顺序的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:35:15