【问题标题】:Sheet inside ForEach doesn't loop over items SwiftUIForEach 中的工作表不会遍历项目 SwiftUI
【发布时间】:2020-11-15 05:22:42
【问题描述】:

我在 ForEach 中使用工作表时遇到问题。基本上我有一个列表,它显示了我的数组中的许多项目和一个触发工作表的图像。问题是当我的工作表出现时,它只显示我的数组的第一项,在这种情况下是“哈利波特”。

这是代码

struct ContentView: View {
    @State private var showingSheet = false
    
    var movies = ["Harry potter", "Mad Max", "Oblivion", "Memento"]
    var body: some View {
        NavigationView {
            List {
                ForEach(0 ..< movies.count) { movie in
                    HStack {
                        Text(self.movies[movie])
                        Image(systemName: "heart")
                    }
                        .onTapGesture {
                            self.showingSheet = true
                    }
                    .sheet(isPresented: self.$showingSheet) {
                        Text(self.movies[movie])
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 如果 Asperi 的回答对您有用,您可以将其标记为“已接受”。

标签: swift foreach swiftui


【解决方案1】:

应该只有一个工作表,所以这里有可能的方法 - 使用另一个工作表修饰符并通过选择激活它

使用 Xcode 12 / iOS 14 测试(兼容 iOS 13)

extension Int: Identifiable {
    public var id: Int { self }
}

struct ContentView: View {
    @State private var selectedMovie: Int? = nil

    var movies = ["Harry potter", "Mad Max", "Oblivion", "Memento"]
    var body: some View {
        NavigationView {
            List {
                ForEach(0 ..< movies.count) { movie in
                    HStack {
                        Text(self.movies[movie])
                        Image(systemName: "heart")
                    }
                        .onTapGesture {
                            self.selectedMovie = movie
                    }
                }
            }
            .sheet(item: self.$selectedMovie) {
                Text(self.movies[$0])
            }
        }
    }
}

【讨论】:

  • 我展示的这个示例非常简单,它可以按照您的更改方式工作,但我有一个更复杂的情况,我需要跟踪数组中项目的位置,我也单击按钮时需要关闭工作表。有没有其他方法可以在不使用@State 属性调用的情况下解决此问题?
  • 我只是不明白为什么当我在 ForEach 中使用 Sheet 时,它不会在循环时跟踪“电影”位置。那 self.movi​​es[movie] 应该每次都改变,但它不会
  • 当您在 ForEach 中添加 .sheet 修饰符时,您会添加许多工作表(每行一个)连接到一个此状态,因此切换一个状态您会激活 所有 个工作表,从而导致不可预知的行为。您需要一张纸和一个选定的项目,按索引或直接按项目 - 这是按偏好。
  • 哦,好的,我现在明白了。我会尝试在此基础上调整一切。谢谢
  • 如果您有自定义对象而不是字符串,请查看这篇文章。 hackingwithswift.com/books/ios-swiftui/…
【解决方案2】:

我将您的代码更改为只有一张纸,并将所选电影放在一个变量中。

extension String: Identifiable {
    public var id: String { self }
}

struct ContentView: View {
    @State private var selectedMovie: String? = nil
    
    var movies = ["Harry potter", "Mad Max", "Oblivion", "Memento"]
    var body: some View {
        NavigationView {
            List {
                ForEach(movies) { movie in
                    HStack {
                        Text(movie)
                        Image(systemName: "heart")
                    }
                    .onTapGesture {
                        self.selectedMovie = movie
                    }
                }
            }
            .sheet(item: self.$selectedMovie, content: { selectedMovie in
                Text(selectedMovie)
            })
        }
    }
}

【讨论】:

    【解决方案3】:

    想在这件事上给我 2 美分。 我遇到了同样的问题,Asperi 的解决方案对我有用。 但是 - 我还想在表单上有一个按钮来关闭模式。

    当您使用 isPresented 调用 sheet 时,您传递了一个绑定 Bool,因此您将其更改为 false 以关闭。 我在item 案例中所做的是将项目作为绑定传递。在工作表中,我将绑定项更改为 nil 并取消了工作表。

    因此,例如在这种情况下,代码将是:

    var movies = ["Harry potter", "Mad Max", "Oblivion", "Memento"]
    var body: some View {
        NavigationView {
            List {
                ForEach(0 ..< movies.count) { movie in
                    HStack {
                        Text(self.movies[movie])
                        Image(systemName: "heart")
                    }
                        .onTapGesture {
                            self.selectedMovie = movie
                    }
                }
            }
            .sheet(item: self.$selectedMovie) {
                Text(self.movies[$0])
    
                // My addition here: a "Done" button that dismisses the sheet
    
                Button {
                    selectedMovie = nil
                } label: {
                    Text("Done")
                }
    
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-30
      • 2019-11-02
      • 2019-05-14
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      相关资源
      最近更新 更多