【问题标题】:iOS14 introducing errors with @State bindingsiOS14 引入 @State 绑定错误
【发布时间】:2021-01-03 19:09:21
【问题描述】:

下面的 swiftUI 代码在 iOS13 上运行良好,但在使用 iOS14 进行测试时,我在尝试显示模式表时遇到了由强制解包选项引起的致命错误。据我所知,工作表不应该尝试显示 selectedModel 的 nil 值,因为仅在分配 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]它的行为与预期完全一样:第一次按下任何菜单项时,第一项被传递给工作表,但在关闭工作表并选择另一个项目时它会显示每次都是正确的项目。因此,分配 selectedModel 的按钮就好像在分配工作表之前尝试显示工作表一样。

【问题讨论】:

  • 视图创建顺序是未定义的,所以你永远不应该依赖它。最适合您的方案的解决方案是通过.sheet(item... 修饰符,如下面的@pawello2222 答案。
  • 我刚刚在切换到 iOS 14 时遇到了这个问题 - Apple 的错误非常严重。

标签: ios swift swiftui ios14


【解决方案1】:

看起来在 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()
            }
    }
}

【讨论】:

  • 谢谢,这适用于这种情况。但是我看不到如何在类似的情况下实现这一点,我想根据按下的按钮从几张纸中进行选择。我用我的意思的例子编辑了我的帖子
  • @Neil 请不要编辑您的帖子 - 每个帖子一个问题。用您的新问题创建另一个帖子 - 我会尽力为您提供帮助。
  • 抱歉,这里有后续问题:stackoverflow.com/questions/63938343/…谢谢!
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多