SwiftUI 中子结构的计算属性未更新
Posted
技术标签:
【中文标题】SwiftUI 中子结构的计算属性未更新【英文标题】:Computed Property from Child Struct Not Updating in SwiftUI 【发布时间】:2021-10-16 04:45:38 【问题描述】:我的 SwiftUI 应用中有一个数据模型,看起来像这样:
struct Entry: Identifiable
var id = UUID().uuidString
var name = ""
var duration: Int
//An SQLite query that returns the total of the "duration" column
let total = try! dbc.scalar(tableFlight.filter(db.entry == id).select(db.duration.total))
return Int(total)
struct Flight: Identifiable
var id = UUID().uuidString
var duration = 0
var entry: String?
我有一个ObservableObject
视图模型,它生成如下条目:
class EntryModel: ObservableObject
static let shared = EntryModel()
@Published var entries = [Entry]()
init()
get()
func get()
//Stuff to fetch the entries
entries = //SQLite query that returns an array of Entry objects
最后,在我的View
中,我列出了所有条目名称及其关联的duration
,如下所示:
ForEach(modelEntry.entries) entry in
VStack
Text(entry.name) //<-- Updates fine
Text(entry.duration) //<-- Gets set initially, but no updates
我遇到的问题是,当我为 Entry
更新 Flight
时,我认为 duration
不会更新。我知道这不会发生,因为只有 entries
会在更改时重绘。
但即使我在EntryModel
中手动调用get()
函数,关联的duration
仍然不会更新。
有没有更好的方法来做到这一点?如何让父元素的计算属性在其子元素更新时重新计算?
【问题讨论】:
在get()
之后调用objectWillChange.send()
怎么样?我不确定这是否可行,但值得一试——至少它会向 View 发出尝试更新的信号。
我不明白的是,您的持续时间甚至不是来自您的入门模型中的任何内容。那么你到底在你的入门模型中更新了什么?因为 dbc 不在您的模型中。我只能假设(并且担心)它是某种全局变量(或者你使用小写的类来混淆读者)。
如duration
属性下的注释所示,这是一个返回相关数据的SQLite查询。 dbc
是一个数据库单例。不过,这与手头的问题并不真正相关。
抱歉,这只是反值类型编码。值类型不应该有这样的隐藏依赖关系,特别是如果在不同的时间点使用,它的行为会有所不同。那最好是一个全局函数,或者更好的是,它是暴露dbc
依赖项的类的一部分。
我明白了。不要那样做。它会伤害你。将该查询放入初始化程序中。每次重新渲染视图时都会运行您的查询,不仅仅是为了描述,而是为了任何目的。
【参考方案1】:
我想通了。我的实际代码在ForEach
中使用了一个孩子View
,其中VStack
是。我只是将entry
传递给它,所以这些值只是最初设置的,因此没有反应。
通过将 entry
更改为 Binding
,它正在工作:
ForEach($modelEntry.entries) $entry in
ChildView(entry: $entry)
请注意,$modelEntry
上的 $
和返回 $entry
是 Xcode 13+ 功能(但向后兼容 ios 14 和 macOS 11.0)。
【讨论】:
以上是关于SwiftUI 中子结构的计算属性未更新的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 计算属性显示“在视图更新期间修改状态,这将导致未定义的行为。”错误