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

SwiftUI中调用结构体mutating方法报错的原因及解决办法

错误原因与修复方案

错误原因

  • Swift的结构体是值类型,mutating方法的作用是修改结构体实例本身的状态。
  • 你直接通过CritterData().addCritter(critter: Ziggy)调用时,CritterData()创建的是一个临时的不可变实例(未赋值给变量时,Swift默认将其视为不可变),因此无法调用需要修改实例的mutating方法。
  • 而getCritterData()是非mutating方法,不需要修改实例状态,所以可以直接调用临时实例的该方法。

修复方法

方案1:临时使用实例(仅单次操作)

将临时实例赋值给可变变量,再调用mutating方法。同时注意不要直接在body顶层执行数据操作,改用视图生命周期回调(比如onAppear):

struct CritterView: View {
    @Binding var critterViewIsShowing: Bool

    var body: some View {
        VStack{
            CritterViewHeader(critterViewIsShowing: $critterViewIsShowing)
        }
        .onAppear {
            // 创建可变的CritterData实例
            var tempCritterData = CritterData()
            tempCritterData.addCritter(critter: Ziggy)
        }
    }
}

方案2:在视图中持久化管理实例

如果需要在视图生命周期内保持CritterData的状态(比如后续要访问crittersArray),可以用SwiftUI的@State来管理结构体实例:

struct CritterView: View {
    @Binding var critterViewIsShowing: Bool
    // 用@State让SwiftUI管理结构体实例的生命周期
    @State private var critterData = CritterData()

    var body: some View {
        VStack{
            CritterViewHeader(critterViewIsShowing: $critterViewIsShowing)
        }
        .onAppear {
            // 直接调用mutating方法,@State保证实例是可变的
            critterData.addCritter(critter: Ziggy)
        }
    }
}

方案3:跨视图共享数据(推荐)

如果需要在多个视图间共享CritterData,可以将其改为ObservableObject类(引用类型,无需mutating方法),用@StateObject管理:
首先修改CritterData:

import Combine

class CritterData: ObservableObject {
    // @Published让属性变化时自动通知视图刷新
    @Published var crittersArray: [Critter] = []

    func addCritter(critter: Critter){
        print(critter.name)
        crittersArray.append(critter)
    }

    func getCritterData(){
       print("This is critter data")
    }
}

然后在视图中使用:

struct CritterView: View {
    @Binding var critterViewIsShowing: Bool
    // @StateObject负责管理ObservableObject的生命周期
    @StateObject private var critterData = CritterData()

    var body: some View {
        VStack{
            CritterViewHeader(critterViewIsShowing: $critterViewIsShowing)
        }
        .onAppear {
            critterData.addCritter(critter: Ziggy)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:35:01