SwiftUI 视图首选项:overlayPreferenceValue 在复杂容器上使用时返回 nil
Posted
技术标签:
【中文标题】SwiftUI 视图首选项:overlayPreferenceValue 在复杂容器上使用时返回 nil【英文标题】:SwiftUI view preferences: overlayPreferenceValue returns nil when used on complex containers 【发布时间】:2020-05-26 07:54:20 【问题描述】:我正在尝试使用anchorPreference
在我的 VStack 中的某些视图上绘制叠加层。
但是,它只适用于最简单的情况。当我的 VStack 的内容变得有点复杂时,覆盖层永远不会被绘制。
这是我的代码
struct debug_test: View
@State private var someState = false
var body: some View
VStack
Text("Hello World !!!")
.anchorPreference(
key: BoundsPreferenceKey.self,
value: .bounds
) $0
//////////////////////////////////////////////////////////
// When I remove below lines - it works ok.
// But when I put add some conditionally-visible view and one more view
// it stops drawing an overlay.
// Apparently, `preferences` is always nil in that case.
if someState
Text("Pooop")
Text("Pooop2")
//////////////////////////////////////////////////////////
.overlayPreferenceValue(BoundsPreferenceKey.self) preferences in
GeometryReader geometry in
preferences.map
Rectangle()
.stroke(Color.red, lineWidth: 5)
.frame(
width: geometry[$0].width,
height: geometry[$0].height
)
.offset(
x: geometry[$0].minX,
y: geometry[$0].minY
)
正如我在代码 cmets 中解释的那样,当我得到一个内部只有一个视图的简单堆栈时,它可以正常工作。但是当我在里面添加更多视图和一些条件时,它就停止工作了。 任何线索如何解决它?
【问题讨论】:
【参考方案1】:首选项在布局期间更新,我假设您的首选项键持有Anchor<CGRect>?
,它在布局结束时被重置为零。
这是固定的变体。使用 Xcode 11.4 / ios 13.4 测试。
注意:我建议为您的自定义首选项键使用显式结构模型。考虑this solution for example
struct BoundsPreferenceKey: PreferenceKey
static var defaultValue: [Anchor<CGRect>] = [] // << use something persistent
static func reduce(value: inout [Anchor<CGRect>], nextValue: () -> [Anchor<CGRect>])
value.append(contentsOf:nextValue())
struct debug_test: View
@State private var someState = false
var body: some View
VStack
Text("Hello World !!!")
.anchorPreference(
key: BoundsPreferenceKey.self,
value: .bounds
) [$0]
if someState
Text("Pooop")
Text("Pooop2")
//////////////////////////////////////////////////////////
.overlayPreferenceValue(BoundsPreferenceKey.self) preferences in
GeometryReader geometry in
preferences.map
Rectangle()
.stroke(Color.red, lineWidth: 5)
.frame(
width: geometry[$0].width,
height: geometry[$0].height
)
.position( // << here is fix as well !!
x: geometry[$0].midX,
y: geometry[$0].midY
)
[0] // << just for demo, this should be more safe !!
【讨论】:
以上是关于SwiftUI 视图首选项:overlayPreferenceValue 在复杂容器上使用时返回 nil的主要内容,如果未能解决你的问题,请参考以下文章