代码之家  ›  专栏  ›  技术社区  ›  zumzum

引用了并发执行代码中捕获的var?

  •  1
  • zumzum  · 技术社区  · 2 年前

    我有以下代码:

    import SwiftUI
    import Observation
    
    struct ContentView: View {
    
        @State var vm = ViewModel()
        
        var body: some View {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
            }
            .padding()
        }
        
    }
    
    @Observable class ViewModel {
        
        struct TestInfo {
            var myId:Int
        }
        
        @MainActor var info:TestInfo?
        
        func setupInfo() async {
            
            var tmp:TestInfo?
            
            await CoreData.shared.context.perform {
    
                /// some core data work and then we set tmp
                tmp = TestInfo(myId: ....)
            }
            
            
            await MainActor.run {
                info = tmp /// ERROR: Reference to captured var 'tmp' in concurrently-executing code
            }
            
        }
        
    }
    

    我想知道如何修复这个错误。I设置 tmp 在核心数据上下文闭包中,然后希望设置 info tmp .

    1 回复  |  直到 2 年前
        1
  •  1
  •   Rob Napier    2 年前

    你的 ViewModel 应该注释 @MainActor 因为它驱动UI。这将确保 setupInfo 是关于主要参与者的,并消除了对的需要 MainActor.run 这是在制造麻烦。

    此外,您不应该设置 tmp 并在其他地方进行修改。相反,让 perform 返回您的价值:

    self.info = CoreData.shared.context.perform {
         /// some core data work
         return TestInfo(myId: ....)
    }
    

    总的来说,它看起来是这样的:

    @MainActor @Observable class ViewModel {
    
        struct TestInfo {
            var myId:Int
        }
    
        var info:TestInfo?
    
        func setupInfo() async {
            info = await CoreData.shared.context.perform {
    
                /// some core data work and then we set tmp
                tmp = TestInfo(myId: ....)
            }
        }
    }