[Error]Swift方法中修改传参对象报错Left side of mutating operator isn‘t mutable: ‘question‘ is a ‘let‘ constant

问题:

代码如下,QuestionExModel是结构体,在方法中更新对象中的参数会报错Left side of mutating operator isn't mutable: 'question' is a 'let' constant

func updateTestState(_ question: QuestionExModel) {
    if question.answerState == 1 {
        question.correctCount += 1
    } else if question.answerState == 2 {
        question.wrongCount += 1
    }
}

原因:

在Swift中,函数参数默认是常量(let),这意味着它们不能被修改。错误信息表明你正在尝试修改一个常量参数question。

修复:

为了修复这个问题,你需要将question参数标记为可变的。你可以通过将参数定义为inout来实现这一点,这样就可以从函数内部修改参数的值,并且修改会反映到函数外部。请注意,使用inout参数时,你需要在传递参数时使用&符号来指示这是一个引用传递。

以下是修改后的函数:

func updateTestState(_ question: inout QuestionExModel) {
    if question.answerState == 1 {
        question.correctCount += 1
    } else if question.answerState == 2 {
        question.wrongCount += 1
    }
}

调用这个函数时,你需要这样做:

var myQuestion = // ...some existing QuestionExModel
updateTestState(&myQuestion)

注意:

如果将inout修饰的值传到闭包中,会报错Escaping closure captures 'inout' parameter 'question'

func updateQuestionAnswerState(question: inout QuestionExModel){
    TestPager.getDatabase().executeInDatabase { [weak self] database in
        database.updateSelectedAnswer(sessionKey: self?.sessionKey ?? "", question: &question)
    }
}

如果真的需要在闭包中修改 question,通常的做法是使用一个完成处理器(completion handler),这样可以在闭包执行完成后返回修改后的结果。

以下是这种方法的一个示例:

func updateQuestionAnswerState(question: QuestionExModel, completion: @escaping (QuestionExModel) -> Void) {
    Database().executeInDatabase { [weak self] database in
        // 假设我们有一个方法可以修改 question 并返回修改后的结果
        let updatedQuestion = database.updateSelectedAnswer(question: question)
        
        // 在闭包执行完毕后,通过 completion handler 返回更新后的 question
        DispatchQueue.main.async {
            completion(updatedQuestion)
        }
    }
}

// 使用这个方法时:
var myQuestion = // ... some existing QuestionExModel
updateQuestionAnswerState(question: myQuestion) { updatedQuestion in
    // 这里你可以访问和使用修改后的 myQuestion
    myQuestion = updatedQuestion
    // 进行其他需要的操作
}