【问题标题】:How can I remove an item from a ForEach inside of a TabView using SwiftUI?如何使用 SwiftUI 从 TabView 内的 ForEach 中删除项目?
【发布时间】:2021-07-17 03:03:24
【问题描述】:

我遇到了奇怪的 SwiftUI 崩溃,我无法理解。我有一个 TabView,里面有 3 个图像的列表。我试图通过点击屏幕上的按钮从列表中删除第一张图片,但我遇到了这个崩溃。

'NSInternalInconsistencyException',原因:'尝试删除并重新加载相同的索引路径( {length = 2, path = 0 - 0})' 以 NSException 类型的未捕获异常终止

如果我从代码中删除 TabView,它会按预期工作并删除第一项。这是重现此崩溃所需的最少代码量。我还在这里创建了此代码的 Git 存储库 -> https://github.com/cameronhenige/TestCrash 有人可以帮我弄清楚发生了什么吗?

import SwiftUI

struct ContentView: View {
    @StateObject var testViewModel = TestViewModel()
    
    var body: some View {
        GeometryReader { proxy in
            
            ScrollView {
                
                VStack(alignment: .leading, spacing:0) {
                    
                    TabView {
                        
                        ForEach(testViewModel.images, id: \.self) { image in
                            Image(image)
                        }
                        
                    }.tabViewStyle(PageTabViewStyle())
                    .clipShape(RoundedRectangle(cornerRadius: 15))
                    .padding()
                    .frame(width: proxy.size.width, height: proxy.size.height/2.5)
                    
                }
                Button(action: {
                    testViewModel.removeFirst()
                }) {
                    Text("Remove first item from list")
                }
                
            }
            
            
        }.frame(maxWidth: .infinity).background(Color.black)
    }
}
import Foundation

class TestViewModel: NSObject, ObservableObject {
    
    @Published var images: [String] = ["dog", "cat", "bird"]
    
    func removeFirst() {
        images.remove(at: 0)
    }
}

【问题讨论】:

标签: xcode swiftui swiftui-tabview


【解决方案1】:
TabView {
    
    ForEach(testViewModel.images, id: \.self) { image in
        Image(image)
    }
    
}.tabViewStyle(PageTabViewStyle())
.clipShape(RoundedRectangle(cornerRadius: 15))
.padding()
.frame(width: proxy.size.width, height: proxy.size.height/2.5).id(testViewModel.images.count)

向 TabView 添加 id 可解决此问题!

【讨论】:

    【解决方案2】:

    我想我会解释为什么你的回答解决了这个问题:

    更多关于为什么使用.id(_:) 为您解决问题的解释,这是因为当testViewModel.images.count 更改(也就是视图现在使用不同的数据)时,您会因为 ID 已更改而使视图无效。

    有关使视图无效以及如何修复奇怪的视图更新的更多信息,请参阅Demystify SwiftUI - WWDC21 谈话。

    【讨论】:

      猜你喜欢
      • 2021-02-19
      • 1970-01-01
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 2010-11-02
      • 2021-08-29
      • 2022-01-21
      • 2021-03-27
      相关资源
      最近更新 更多