代码之家  ›  专栏  ›  技术社区  ›  mica

SwiftUI从ForEach中的按钮打开工作表并传递参数[复制]

  •  0
  • mica  · 技术社区  · 4 年前

    下面的swiftUI代码在iOS13上运行良好,但在iOS14的测试中,我在尝试显示模式表时遇到了由强制展开选项引起的致命错误。据我所知,工作表永远不应该为selectedModel提供nil值,因为showingDetails只有在分配selectedModel后才会变为true?

    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] 它的行为与预期完全一致:第一次按下任何菜单项时,第一个项目将传递给工作表,但在关闭工作表并选择另一个项目时,它每次都会显示正确的项目。因此,分配选定模型的按钮似乎试图在分配时间之前显示工作表。

    0 回复  |  直到 4 年前
        1
  •  8
  •   pawello2222    4 年前

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

    尝试使用 sheet(item:content:) 相反:

    var body: some View {
        List {
            ...
        }
        .sheet(item: self.$selectedModel) {
            SpeakerDetailView(speaker: $0)
        }
    }
    

    并使用以下命令关闭纸张 @Environment(\.presentationMode) :

    struct SpeakerDetailView: View {
        @Environment(\.presentationMode) private var presentationMode
        var speaker: Speaker
    
        var body: some View {
            Text("Speaker view")
                .onTapGesture {
                    presentationMode.wrappedValue.dismiss()
                }
        }
    }