How do I correctly pass a “cell item” to a .sheet from a SwiftUI LazyVGrid?

浪子不回头ぞ 提交于 2020-11-25 03:40:33

问题


Here is my example, and I can't tell if this is a bug or not. All my cells load correctly, but when I try to bring up the DetailView() as a sheet, the item pased in is always whatevr item is shown first in the grid (in the top left in my case here), NOT the "cell" that was tapped. So, why is the item from ForEach loop correctly populating the cells, but not being passed to the .sheet via the button?

    import SwiftUI

    let columnCount: Int = 11
    let gridSpacing: CGFloat = 1

    struct GridView: View {
        
        @State var showingDetail = false
        
        let data = (1...755).map { "\($0)" }
        let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
        let colCount: CGFloat = CGFloat(columnCount)
        var body: some View {
            GeometryReader { geo in
                ScrollView (showsIndicators: false) {
                    LazyVGrid(columns: columns, spacing: gridSpacing) {
                        ForEach(data, id: \.self) { item in
                            
                            Button(action: {
                                self.showingDetail.toggle()
                            }) {
                                GridCell(item: item, size: (geo.size.width - (colCount * gridSpacing)) / colCount)
                            }.sheet(isPresented: $showingDetail) {
                                DetailView(item: item)
                            }
                        }
                    }
                }
                .padding(.horizontal, gridSpacing)
            }
        }
    }

    struct GridCell: View {
        let isVault: Bool = false
        let item: String
        let size: CGFloat
        var body: some View {
            ZStack {
                Rectangle()
                    .fill(Color.orange)
                    .cornerRadius(4)
                Text(item)
                    .foregroundColor(.white)
                    .font(.system(size: size * 0.55))
            }
            .frame(height: size)
        }
    }

    struct DetailView: View {
        
        let item: String
        
        var body: some View {
            Text(item)
        }
    }

    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            GridView()
                .preferredColorScheme(.dark)
        }
    }

What am I missing? Also, scrolling on my iPad pro 11 is a bit jumpy, does anyone esle see the same behaviour?


回答1:


In such use-case it is more appropriate to use variant of sheet constructed with item, because sheet must be moved out of dynamic content (otherwise you create as many sheets as items in ForEach).

Here is possible solution. Tested with Xcode 12 / iOS 14.

// helper extension because .sheet(item:...) requires item to be Identifiable
extension String: Identifiable {
    public var id: String { self }
}

struct GridView: View {

    @State private var selected: String? = nil

    let data = (1...755).map { "\($0)" }
    let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
    let colCount: CGFloat = CGFloat(columnCount)
    var body: some View {
        GeometryReader { geo in
            ScrollView (showsIndicators: false) {
                LazyVGrid(columns: columns, spacing: gridSpacing) {
                    ForEach(data, id: \.self) { item in

                        Button(action: {
                            selected = item      // store selected item
                        }) {
                            GridCell(item: item, size: (geo.size.width - (colCount * gridSpacing)) / colCount)
                        }
                    }
                }
            }.sheet(item: $selected) { item in     // activated on selected item
                DetailView(item: item)
            }
            .padding(.horizontal, gridSpacing)
        }
    }
}


来源:https://stackoverflow.com/questions/63217260/how-do-i-correctly-pass-a-cell-item-to-a-sheet-from-a-swiftui-lazyvgrid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!