iOS14 使用@State 绑定引入错误

iOS14 introducing errors with @State bindings

下面的 swiftUI 代码在 iOS13 上运行良好,但在 iOS14 上测试时,我在尝试显示模态 sheet。据我所知,sheet 永远不应该尝试为 selectedModel 呈现一个 nil 值,因为 showingDetails 只有在分配 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)
    }
}

有趣的是,如果我将其解包为 speaker: self.selectedModel ?? filteredSpeakers[0],它的行为完全符合预期:第一次按下任何菜单项时,第一项会传递给 sheet,但在关闭时sheet 并选择另一个项目,然后每次都会显示正确的项目。所以就好像分配 selectedModel 的按钮试图在它有时间分配之前显示 sheet。

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

尝试使用 sheet(item:content:) 代替:

var body: some View {
    List {
        ...
    }
    .sheet(item: self.$selectedModel) {
        SpeakerDetailView(speaker: [=10=])
    }
}

并使用 @Environment(\.presentationMode):

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

    var body: some View {
        Text("Speaker view")
            .onTapGesture {
                presentationMode.wrappedValue.dismiss()
            }
    }
}