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
相关产品推荐
相关产品推荐

