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

