【问题标题】:SwiftUI: Is it possible to trigger a set PreferenceKey() from inside an .OnTapGesture?SwiftUI:是否可以从 .OnTapGesture 中触发 set PreferenceKey()?
【发布时间】:2020-06-30 23:46:43
【问题描述】:

我正在开发一个具有以下 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 正确修改了 Cell 视图,但我只能将 Preference 设置附加到 Cell 视图之外,因此每次在 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 视图?我在选定的数据结构上尝试了 State 和 Observables 包装器,但没有得到任何结果。欢迎任何想法!

更新:我一定对 State/Bind 有错误的理解。我在父内容视图中有一个数据结构的@State var,我使用它来更新详细信息子视图。当我将该 Struct var 的 @Bind 添加到 Cell 子视图时,编译器需要我将该 var 添加到 Cell 子视图的参数列表中。当我添加它时,我会收到各种错误。我尝试了许多变体,但放弃了 Bind 以尝试首选项。回想一下,我想将选定的 Cell Struct 向上传递到树,然后向下传递到 Detail。如果您足够大方地看一看,我可以尝试重新创建错误。

【问题讨论】:

  • 如果只读文本,那么我首先想到的是@Binding。有什么问题吗?
  • 我在传递包含 Struct 的数据时遇到了问题,顺便说一句,它是只读的。
  • Selection 是视图状态功能,因此您的 DetailView 可以拥有 @State selectedGlyph 并将绑定传递给每个单元格。

标签: ios swiftui


【解决方案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)
            }
        }
    }
}

【讨论】:

  • State var不应该在顶层,子视图有Bind var吗?我正在遭受稀疏和矛盾的文档;)。另外,如果是 Private,是否不排除父级访问权限?
  • 状态是按设计设计的,只能在拥有视图内修改,因此将其设为私有是一种很好的做法。视图可以将绑定传递给其他视图,但状态的所有者不会改变。
  • 好的,我了解您通过创建本地选定变量(供 Cell 内部使用)检测选择以触发 prefKey 更改的操作!它在所选结构被传递到 PrefKey 的范围内起作用。现在,问题是父视图中的 .OnPrefChanged 仅在首次加载视图时调用,而不是在选择网格中的单元格时调用,即使如上所述,新数据已传递给 Pref。我要解决这个问题一段时间。非常感谢您的见解!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2020-07-10
    • 1970-01-01
    • 2020-10-28
    • 2022-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    相关资源
    最近更新 更多