SwiftUI:PreferenceKey Reduce 方法永远不会被调用
Posted
技术标签:
【中文标题】SwiftUI:PreferenceKey Reduce 方法永远不会被调用【英文标题】:SwiftUI: PreferenceKey Reduce method never gets called 【发布时间】:2020-03-20 22:30:54 【问题描述】:我正在尝试使用 Preferences 将数据向上传递到视图链,但从未调用过 .onPreferenceChange。调查了一下发现,虽然调试器显示执行通过我的 .Preference 修饰符,reduce 方法永远不会被调用来将新值推送到键中。我不知道为什么,也找不到检查 View 的 Preference key:value 数据的方法。
代码如下:
struct LittleTapPrefKey: PreferenceKey
typealias Value = String
static var defaultValue: Value = "A0"
static func reduce(value: inout Value, nextValue: () -> String)
print("Inside Little Reduce \(value)and NextVal = \(nextValue())")
value = nextValue()
这里是单元格视图,点击 QGrid 中的 GlyphCell 实例,设置 Pref 修饰符:
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: 28)
.foregroundColor(.blue)
.onTapGesture
print("Tap on \(self.glyph.Gardiner)")
self.selected.toggle()
.cornerRadius(6.0)
.frame(width: 90.0, height: 100.0, alignment: .center)
.previewLayout(.sizeThatFits)
.background(Group
if self.selected
Color.clear
.preference(key: LittleTapPrefKey.self, value: self.glyph.Gardiner)
// end selected test
// end group
) // end .background
// end cell body view
在 .pref(key:...) 上设置断点后,每次点击单元格时都会触发断点,此时 self.glyph.Gardiner 的值是正确的。
Preference Key Struct "reduce" 函数中的断点或 test Print 语句永远不会被触发。由于 .onPrefChange 永远不会被触发,我必须假设 Value 永远不会改变,但我无法直接查看 Pref 值。
发生了什么事?
【问题讨论】:
【参考方案1】:reduce
在您在一个视图层次结构中多次设置一个偏好键时被调用,因此 SwiftUI 为您提供了以某种方式组合它们的可能性,例如:
.previewLayout(.sizeThatFits)
.preference(key: LittleTapPrefKey.self, value: value1) // 1st time
.background(Group
if self.selected
Color.clear
.preference(key: LittleTapPrefKey.self, value: value2) // 2nd time
在您的情况下,您只有一个值设置器,所以它只是设置并且.onPreferenceChange(LittleTapPrefKey.self)
回调修饰符按预期工作。
使用 Xcode 11.4 / ios 13.4 测试
【讨论】:
我知道reduce的功能,但不知道它在触发更新存储的关键位置方面有多聪明。在我的例子中,self.selected 块中的 set key 语句似乎正在执行,并且字形是正确的,但没有回调。您建议使用(垃圾)值对首选项键进行“第一次调用”,然后将键设置为所需的值。因此,它会在调用单元格视图时两次更改设置。我不明白为什么它需要两个设置,但你的其他建议是正确的,所以我今天早上会试试!再次感谢 Asperi!!!! @BlueskyMed,这不是一个建议,而是 reduce 可以工作的案例演示。当然你不应该设置 pref 两次。 啊!尽管如此,在 QGrid 的第一轮设置之后,父单元中的回调永远不会在选择单元格之后被调用。这是一个奇怪的异常现象!我在 QGrid 父级的父级视图中添加了一个 onPrefChange,它也不会触发。有趣的是,现在触发了 reduce,打印语句中的 NextVal 始终是添加的 setPref 中的“垃圾”值,而不是 isSelected 块内的值! 我在reduce里面加了一个调试器PO stmt,看到每次点击,reduce被调用了20多次!首先使用正确的值,然后使用默认值!回到绘图板!以上是关于SwiftUI:PreferenceKey Reduce 方法永远不会被调用的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中理解通信模式“Preference Key”的问题
在 SwiftUI 中理解通信模式“Preference Key”的问题
SwiftUI:使用matchedGeometryEffect控制视图上的zIndex
SwiftUI |警告:绑定首选项 _ 尝试每帧更新多次。可能的原因?
SwiftUI ScrollView:查找当前在屏幕中心可见的子视图。子视图在 ScrollView 中的位置。偏好键。滚动视图代理