SwiftUI:更改@State不会刷新视图

fd3cxomn  于 12个月前  发布在  Swift
关注(0)|答案(2)|浏览(145)

我有一个基于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
        }
    }
}
vuktfyat

vuktfyat1#

body仅在状态的setter被调用时被调用,如果它的getter之前已经被调用过。这是SwiftUI依赖跟踪的一部分。
在本例中,只有添加调试Text后才会调用状态获取器。这通常发生在你没有正确设计你的真理来源的时候。由于body只读取在其他地方定义的日期,因此您应该将其作为let传递给View,例如。

struct FootprintView: View {

    let jdNow: Double

body将在每次FootprintView初始化时调用不同的jdNow,不需要onReceive。把body想象成“任何let或var都已更改”。
在SwiftUI中更新计时器,最简单的方法是TimelineView,例如。

TimelineView(.periodic(from: startDate, by: 5)) { context in
    FootprintView(jdNow: context.date.julianDate)
}
wfauudbj

wfauudbj2#

您可以提出的一个选项是创建一个@State lazy var path = {<#Get State from your origin View here#>},将状态转发到活动视图,这可能会解决您的问题,并允许更新转发到活动视图。如果这不起作用,你可能想在这里发布一个堆栈跟踪,这样我们就可以解析它。
请注意,这将转发状态的变化,您可以在您的相关位置(创可贴解决方案),如果这是不相关的,请让我知道

相关问题