SwiftUI использует ForEach и onTapGesture для обновления выбранного элемента, вызывающего сбой

У меня есть некоторый код, который я использую, идея состоит в том, что пользователь выбирает карту, которая ему нравится, и отображается лист, чтобы показать больше информации об этой карте. Проблема в том, что если у меня нет Text(selectedCard?.name ?? "Not selected")линия, он падает. Мне просто интересно, что я не понимаю в Swift/SwiftUI, из-за которого это происходит, и как я могу это исправить (поскольку я не хочу, чтобы он говорил, какую карту они выбрали).

Именно там, где появляется лист, он разбивается, когда находит nilзначение для но selectedCardне должен быть равен нулю, когда это выполняется. Если я добавлю, казалось бы, несвязанную строку, чтобы показать, какая карта была выбрана, значение будет установлено нормально, и это не приведет к сбою.

Полный код:

      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() {
        ...
    }
    
}

1 ответ

Ваша проблема, вероятно, связана с тем, что алгоритм сравнения представлений имеет другой результат, если у вас есть текстовое значение, поскольку это будет различием в корневом представлении. Поскольку у вас есть две части состояния, представляющие лист, и вы принудительно разворачиваете одну из них, вы подвергаете себя опасности.

Вы должны избавиться от , затем вместо этого используйте привязку элемента листа. Делать соответствовать , затем перепишите модификатор листа как:

      .sheet(item: $selectedCard) { SpecificCardView(card: $0) } 

Это также сбросит выбранную карту на ноль, когда лист будет закрыт.

Другие вопросы по тегам