SwiftUI 使用 ForEach 和 onTapGesture 来更新导致崩溃的选定元素

SwiftUI using ForEach and onTapGesture to update selected element causing crash

我有一些正在使用的代码,其想法是用户选择他们喜欢的卡片,然后出现 sheet 以显示有关该卡片的更多信息。问题是,如果我没有 Text(selectedCard?.name ?? "Not selected") 行,它就会崩溃。我只是想知道我不明白 Swift/SwiftUI 是什么导致了这种情况发生以及我该如何解决它(因为我不希望它说出他们选择了哪张卡片)。

这是 sheet 出现的地方,它在找到 selectedCardnil 值时崩溃,但 selectedCard 在运行时不应该为 nil .如果我添加看似无关的行来显示选择了哪张卡,则该值设置正常并且不会崩溃。

完整代码:

import SwiftUI

struct CardsView: View {
    
    @State private var cardlist = [Cards]()
    @State private var showingSheet = false
    @State private var selectedCard: Cards?
    
    let columns = [
        GridItem(.adaptive(minimum: 120))
    ]
    
    var body: some View {
        NavigationView() {
            ScrollView (.vertical, showsIndicators: false) {
                Text("View our full collection of cards below:")
                    .padding(.leading, 20)
                    .frame(maxWidth: .infinity, alignment: .leading)
                
                Text(selectedCard?.name ?? "Not selected") // This line stops it from crashing
                
                    LazyVGrid(columns: columns, spacing: 10) {
                        ForEach(cardlist, id: \.name) { thecard in
                            CardItem(card: thecard)
                                .onTapGesture {
                                    selectedCard = thecard
                                    showingSheet.toggle()
                                }
                        }
                        
                    }
                    .padding([.leading, .trailing])
                
                Spacer()
            }
            
            .navigationTitle("Cards")
        }
        
        .sheet(isPresented: $showingSheet) {
            SpecificCardView(card: selectedCard!)
        }
        
        .onAppear() {
            loadCards()
        }
        
    }
    
    func loadCards() {
        ...
    }
    
}

您的问题可能是由于存在文本值时视图差异算法会产生不同的结果,因为这在根视图中会有所不同。由于您有两个代表 sheet 的状态,并且您正在强行解开其中一个,因此您会让自己面临危险。

您应该去掉 showingSheet,然后改用 sheet 的项目绑定。使Cards符合Identifiable,然后将sheet修饰符重写为:

.sheet(item: $selectedCard) { SpecificCardView(card: [=10=]) } 

当 sheet 被关闭时,这也会将您选择的卡片重置为零。