“在视图更新期间修改状态,这将导致未定义行为”的奇怪问题

时间:2021-07-27 23:07:00

标签: swiftui swiftui-navigationlink

目标:拥有一个 SwiftUI 架构,其中“添加新项目”和“编辑现有项目”由同一个视图 (EditItemView) 解决。但是,出于某种原因,当我这样做时,运行时代理会抱怨“在视图更新期间修改状态,这将导致未定义的行为”。

这是我要使用的代码,它确保项目的 EDITING 和 ADDING 新项目由同一个 EditItemView 处理:

var body: some View {
    NavigationView
    {
        
        ScrollView
        {
            LazyVGrid(columns: my_columns)
            {
                ForEach(items, id: \.id)
                {
                    let item = $0
                    
                    // THIS LINE TO EDIT AN EXISTING ITEM
                    NavigationLink(destination: EditItemView(item: item))
                    {
                        ItemView(item: item)
                    }
                    
                }

            }
            
        }
        .navigationBarItems(trailing:
            // THIS LINE TO ADD A NEW ITEM:
            NavigationLink(destination: EditItemView(item: Data.singleton.createItem(name: "New item", value: 5.0))
            {
                Image(systemName: "plus")
            }
        )
    }
}

它不起作用,导致上面突出显示的问题。我被迫将 Edit 和 Add 的功能分成两个不同的视图,然后工作:

var body: some View {
    NavigationView
    {
        
        ScrollView
        {
            LazyVGrid(columns: my_columns)
            {
                ForEach(items, id: \.id)
                {
                    let item = $0
                    
                    // THIS LINE TO EDIT AN EXISTING ITEM
                    NavigationLink(destination: EditItemView(item: item))
                    {
                        ItemView(item: item)
                    }
                    
                }

            }
            
        }
        .sheet(isPresented: $isPresented)
        {
            // FORCED TO USE SEPARATE VIEW
            AddItemView { name, value in
                _ = Data.singleton.createItem(name: name, value: value)
                self.isPresented = false
            }
        }
        .navigationBarItems(trailing: Button(action: { self.isPresented.toggle()}) { Image(systemName: "plus")})
    }
}

我不明白为什么第一个版本中的代码被认为是在更新视图时修改状态,因为对我来说,它是顺序的:创建新项目,然后为该项目显示一个视图。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

NavigationLink 的目标 不会 延迟渲染,这意味着它会在 NavigationLink 本身被渲染时渲染——而不是在点击时渲染。

sheet 代码,取决于平台和 SwiftUI 版本,可能有相同的问题,但显然在您使用的版本中没有。或者,您提供给 AddItemView 的闭包不会立即运行 -- 因为您没有包含代码,所以不清楚。

要解决第一种方法中的问题,您可以使用以下 SO 答案,它提供了一个懒惰的 NavigationLinkhttps://stackoverflow.com/a/61234030/560942