SwiftUI:在展开可选值时意外发现 nil

SwiftUI: Unexpectedly found nil while unwrapping an Optional value

我正在学习斯坦福 iOS 在线课程的 CS193p 开发应用程序。 我正在尝试执行 Assignment 6 (Memorize Themes.pdf).

当我 运行 我的应用程序在模拟器和编辑模式下点击列表行以显示 sheet 时,我收到以下致命错误: 线程 1:致命错误:在展开可选值时意外发现 nil

问题:为什么匹配 themeToEdit themes数组中的索引为nil?

请帮帮我。

import SwiftUI

// Required Task 3: Your Memorize application should now show a “theme chooser” UI when it launches.

struct ThemeChooserView: View {
    @EnvironmentObject var themeStore: ThemeStore
    
    @State private var editMode: EditMode = .inactive
        
    var body: some View {
        NavigationView {
            List {
                ForEach(themeStore.themes) { theme in
                    NavigationLink(destination: EmojiMemoryGameView(game: EmojiMemoryGame(theme: theme))) {
                        VStack(alignment: .leading) {
                            Text(theme.name)
                                .foregroundColor(theme.color)
                                .font(.title)
                            Text(themeCardsDescription(theme: theme))
                        }
                        .gesture(editMode == .active ? tapGesture(theme: theme) : nil)
                    }
                }
                .onDelete { indexSet in
                    themeStore.themes.remove(atOffsets: indexSet)
                }
                .onMove { indexSet, newOffset in
                    themeStore.themes.move(fromOffsets: indexSet, toOffset: newOffset)
                }
            }
            .sheet(isPresented: $isEditing) {
                let currentThemeIndex = themeStore.themes.firstIndex(where: {[=10=].id == themeToEdit?.id})
                ThemeEditor(theme: $themeStore.themes[currentThemeIndex!]) // ERROR: -  Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
            }
            .navigationTitle("Memorize")
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarLeading) {
                    plusButton
                }
                ToolbarItemGroup {
                    EditButton()
                }
            }
            .environment(\.editMode, $editMode)
        }
    }
    
    @State private var isEditing: Bool = false
    
    @State private var themeToEdit: Theme?

    private func tapGesture(theme: Theme) -> some Gesture {
        TapGesture().onEnded { _ in
            themeToEdit = theme
            isEditing = true
        }
    }
    
    private func themeCardsDescription(theme: Theme) -> String {
        let numberOrAll = theme.numberOfPairsOfCards == theme.emojis.count ? "All" : "\(theme.numberOfPairsOfCards)"
        return numberOrAll + " pairs from \(theme.emojis.joined(separator: ""))"
    }
    
    private var plusButton: some View {
        Button {
            let theme = Theme(name: "New Theme", emojis: ["", ""], numberOfPairsOfCards: 2, color: .black)
            themeStore.themes.append(theme)
        } label: {
            Image(systemName: "plus")
        }
    }
}

您正在获取该值,因为该值可能尚未设置,因为 @State 的机制会触发 willSet 上的观察者,而不是 didSet。要解决您的问题,您可以摆脱 isEditing 属性 并完全依赖 themeToEdit 属性.

.sheet(item: $themeToEdit) { theme in
    let index = themeStore.themes.firstIndex(where: { [=10=].id == theme.id })
    ThemeEditor(theme: $themeStore.themes[index!])
}

更新了 tapGesture 实施。

private func tapGesture(theme: Theme) -> some Gesture {
    TapGesture().onEnded { _ in
        themeToEdit = theme
    }
}

文档:sheet(item:onDismiss:content:)