iOS14 使用 @State 绑定引入错误

Nei*_*eil 5 ios swift swiftui ios14

下面的 swiftUI 代码在 iOS13 上运行良好,但在使用 iOS14 进行测试时,我在尝试显示模式表时遇到了由 force-unwrapped optional 引起的致命错误。据我所知,工作表永远不应该尝试为 selectedModel 显示一个 nil 值,因为 ShowDetails 仅在分配 selectedModel 后才变为真?

struct SpeakerBrandMenu: View {
    var filteredSpeakers: [Speaker] {
        // An array of Speaker objects
        }
        
    @State var selectedModel: Speaker?
    @State private var showingDetails = false

    var body: some View {
        List{       
        ForEach(filteredSpeakers) { speaker in
            HStack {
                Button(action: {
                    self.selectedModel = speaker
                    self.showingDetails = true
                }) {
                    SpeakerModelRow(speaker: speaker).contentShape(Rectangle())
                }
                .buttonStyle(PlainButtonStyle())

                Spacer()
                
                Button(
                //unrelated
                ).padding(5)
              }
            }
        } .sheet(isPresented: self.$showingDetails) { SpeakerDetailView(speaker: self.selectedModel!, showSheet: self.$showingDetails).environmentObject(self.favoriteSpeakers).environmentObject(self.settings)}
               
          .navigationBarTitle(Text(brand), displayMode: .inline)
    }
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果我speaker: self.selectedModel ?? filteredSpeakers[0]按照预期的方式打开它:第一次按下任何菜单项时,第一个项目会传递到工作表,但是在关闭工作表并选择另一个项目时,它每次都会显示正确的项目。所以就好像分配 selectedModel 的按钮试图在它有时间分配之前显示工作表。

paw*_*222 7

看起来在 iOS 14sheet(isPresented:content:)中现在是预先创建的,因此selectedModel忽略了对其所做的任何更改。

尝试使用sheet(item:content:)

var body: some View {
    List {
        ...
    }
    .sheet(item: self.$selectedModel) {
        SpeakerDetailView(speaker: $0)
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用@Environment(\.presentationMode)以下方法关闭工作表:

struct SpeakerDetailView: View {
    @Environment(\.presentationMode) private var presentationMode
    var speaker: Speaker

    var body: some View {
        Text("Speaker view")
            .onTapGesture {
                presentationMode.wrappedValue.dismiss()
            }
    }
}
Run Code Online (Sandbox Code Playgroud)