SwiftUI:是否可以从.OnTapGesture内部触发设置的PreferenceKey()?

时间:2020-03-19 19:39:18

标签: ios swiftui

我正在开发具有以下ContentView结构的应用程序

    ContentView {
    ---HeaderView
    ---Collection view using QGrid (An Array of Cells), data source: an array of Structs
    ---A Detail View of data from a single data Struct from the data array
}

目标是使用来自QGrid中被轻击的单元格中的数据更新Detail子视图。 我有一个单元格视图,它可以识别水龙头并正确报告要控制台的单元格。 .OnTap可以正确修改“单元格”视图,但是我只能将“首选项”设置附加到“单元格”视图之外,因此,每次在QGrid中显示一个单元格时,都会触发Pref的更改,从而使报告的单元格成为网格中的最后一个单元格,但点击时永远不会更新到所选单元格!

struct GlyphCell: View {

    var glyph:Glyph

    var body: some View {
        ZStack {
            Text("\(glyph.Hieroglyph)")
                .lineLimit(1)
                .padding(.all, 12.0)
                .font(.system(size: 40.0))
                .background(Color.yellow)
            Text("\(glyph.Gardiner)")
                .offset(x: 12, y: 26)
                .foregroundColor(.blue)
        }.onTapGesture {
            print("Tap on \(self.glyph.Gardiner)")
            DispatchQueue.main.async {
                // would like to update preference in here!
                }
            }
        .preference(key: TappedGlyphPreferenceKey.self, value: self.glyph)
        .cornerRadius(6.0)
        .frame(width: 90.0, height: 100.0, alignment: .center)
        .previewLayout(.sizeThatFits)
    }
}

是否可以通过这种方法来实现,即将Pref传递给父视图,然后传递给目标的Detail视图?我在选定的数据Struct上尝试了State和Observables包装器,但没有成功。欢迎任何想法!

更新:我必须对状态/绑定有错误的了解。我在父Content View中使用数据结构的@State变量,用于更新Detail子视图。当我将该Struct变量的@Bind添加到Cell子视图时,编译器随后需要我将该变量添加到Cell子视图的参数列表中。当我添加它时,我会遇到各种各样的错误。我尝试了多种变体,但放弃了Bind尝试偏好。回想一下,我想将选定的单元结构向上传递到树,然后向下传递到“细节”。如果您足够慷慨地窥视一下,我可以尝试重新创建该错误。

2 个答案:

答案 0 :(得分:1)

尝试以下操作(由于缺少很多依赖项,因此无法测试,仅是主意)

struct GlyphCell: View {

    var glyph:Glyph

    @State private var selected = false   // << track own selection
    var body: some View {
        ZStack {
            Text("\(glyph.Hieroglyph)")
                .lineLimit(1)
                .padding(.all, 12.0)
                .font(.system(size: 40.0))
                .background(Color.yellow)
            Text("\(glyph.Gardiner)")
                .offset(x: 12, y: 26)
                .foregroundColor(.blue)
        }.onTapGesture {
            print("Tap on \(self.glyph.Gardiner)")
            self.selected.toggle() // << async not required here
        }
        .cornerRadius(6.0)
        .frame(width: 90.0, height: 100.0, alignment: .center)
        .previewLayout(.sizeThatFits)
        .background(Group {
           if self.selected {
                // activate preference only when selected
                Color.clear
                    .preference(key: TappedGlyphPreferenceKey.self, value: self.glyph)
            }
        }
    }
}

答案 1 :(得分:1)

另一种可能的方法: 将首选项值保留为状态变量。 点击手势时,请更改状态变量。 将首选项修改器附加到视图,然后将State变量设置为首选项值。