我有一个基于SwiftUI的应用程序,这让我很困惑。它的一个视图有一个@State变量,该变量用于计算以创建在上下文视图中显示的路径。这个变量在一个计时器上改变,我希望视图在发生这种情况时更新。
但是主FootprintView
视图不会刷新,除非我将该变量(jdNow
)作为视图呈现层次结构的显式部分。在下面的代码中,除非包含变量的Text
视图存在,否则视图不会刷新。删除它并停止刷新。
我相信计算中调用的各种方法(我在这里没有显示)是正确的,当Text
View存在时(以及它们在其他应用程序中的使用)的正确渲染证明了这一点。我目前的解决方法是保留Text
,但使用.opacity(0.0)
使其不可见。
为什么?我检查了.onReceive
修饰是否会在Text
存在或不存在的情况下更改变量,因此@State正在更改。很明显,我不明白国家是如何运作的。有人能教教我吗
struct FootprintView: View {
@State private var jdNow: Double = Date.now.julianDate
var body: some View {
Text("\(jdNow)").opacity(0.0) //## needed to force the periodic redraw (why) ..
Canvas { context, size in
let mercatorContext = context.mercatorCoords(size) // change to Mercator coordinates ..
let visualGroup = . . .
for elements in visualGroup. . . {
let satellite = Satellite(elements: elements)
let minsAfterEpoch = (jdNow - JD.epoch1950 - satellite.t₀Days1950) * 1440.0
let satCel = satellite.position(minsAfterEpoch: minsAfterEpoch)
let satLLH = eci2geo(julianDays: jdNow, celestial: satCel)
let footprintPath = drawFootprint(satGeo: satLLH)
mercatorContext.stroke(footprintPath, with: .color(.white), lineWidth: 0.2)
}
}
.onReceive(global5SecTimer) { _ in
jdNow = Date.now.julianDate
}
}
}
2条答案
按热度按时间vuktfyat1#
body
仅在状态的setter被调用时被调用,如果它的getter之前已经被调用过。这是SwiftUI依赖跟踪的一部分。在本例中,只有添加调试
Text
后才会调用状态获取器。这通常发生在你没有正确设计你的真理来源的时候。由于body
只读取在其他地方定义的日期,因此您应该将其作为let
传递给View
,例如。body
将在每次FootprintView
初始化时调用不同的jdNow
,不需要onReceive
。把body
想象成“任何let或var都已更改”。在SwiftUI中更新计时器,最简单的方法是
TimelineView
,例如。wfauudbj2#
您可以提出的一个选项是创建一个
@State lazy var path = {<#Get State from your origin View here#>}
,将状态转发到活动视图,这可能会解决您的问题,并允许更新转发到活动视图。如果这不起作用,你可能想在这里发布一个堆栈跟踪,这样我们就可以解析它。请注意,这将转发状态的变化,您可以在您的相关位置(创可贴解决方案),如果这是不相关的,请让我知道