在init()构造函数中初始化的@State的SwiftUI视图
我有这样一个简单的复选标记SwiftUI视图。 它显示在列表中,可以通过点击来切换,也可以在从数据源(例如核心数据)刷新时进行切换 我的第一个实现是在init()构造函数中初始化的@State的SwiftUI视图,swift,swiftui,swiftui-state,Swift,Swiftui,Swiftui State,我有这样一个简单的复选标记SwiftUI视图。 它显示在列表中,可以通过点击来切换,也可以在从数据源(例如核心数据)刷新时进行切换 我的第一个实现是 struct RoundedCheckmark: View { @State var isChecked : Bool let onCheck: (Bool) -> Void func toggle() { isChecked = !isChecked; onCheck(isChecked) } init
struct RoundedCheckmark: View {
@State var isChecked : Bool
let onCheck: (Bool) -> Void
func toggle() { isChecked = !isChecked; onCheck(isChecked) }
init(isChecked: Bool, onCheck: @escaping (Bool) -> Void = { _ in }) {
self._isChecked = State(initialValue: isChecked)
self.onCheck = onCheck
}
var body: some View {
Button(action: toggle) {
Image(isChecked ? "CheckedCheckmark" : "UncheckedCheckmark")
}
}
}
它似乎工作,我可以切换它,它加载正确。在切换时,我通过onCheck闭包/回调保存了更改,并刷新了ok
但在外部刷新(如推送通知)之后,刷新此视图的核心数据中的底层模型不会正确更改@State属性
在init()中,我将获得isChecked的新值,并使用State(initialValue:)重新初始化@State。但在主体中,我从旧的@State属性中得到了isChecked的旧值。因此,视图的图像确实是错误的
这里是一种解决方法,即仅依赖let isChecked属性和onCheck回调。但现在我的视图中不能有状态,我只能依靠外部数据源的更改。也许这更合适,因为这样我就有了一个没有本地@State存储的单一真相来源
struct RoundedCheckmark: View {
let isChecked: Bool
let onCheck: (Bool) -> Void
func toggle() { onCheck(isChecked) }
init(isChecked: Bool, onCheck: @escaping (Bool) -> Void = { _ in }) {
self.isChecked = isChecked
self.onCheck = onCheck
}
var body: some View {
Button(action: toggle) {
Image(isChecked ? "CheckedCheckmark" : "UncheckedCheckmark")
}
}
}
isChecked
,因为@State
变量是真理的源泉。这意味着,当一些底层数据模型(如CoreData)发生变化时,这并不重要。您的视图仅查看已检查的的本地@状态
版本
但是看看你的观点。对我来说,它不应该拥有自己的状态。为什么?因为此视图作为复选标记视图没有语义意义。它的父级似乎拥有该状态(因此存在onCheck
回调)。相反,应该使用不带回调的@Binding
:
struct rounded复选标记:视图{
@已检查绑定变量:Bool
var body:一些观点{
按钮(操作:{isChecked.toggle()}){
图像(已选中?“选中选中选中标记”:“未选中选中选中标记”)
}
}
现在,您的父母拥有该州,您可以推断其语义含义:
struct CheckmarkOwner:视图{
@状态变量showFavoritesOnly=false
var body:一些观点{
//内容
圆形复选标记(选中:$showFavoritesOnly)
//现在,当切换“showFavoritesOnly”时,会通知其他内容
如果只表现得好的话{
//可切换内容
}
//更多内容
}
}
看起来您已经回答了自己的问题……是的,但我不明白为什么第一个解决方案不起作用。这是因为每个视图实例都创建了新的@State,但视图使用的是旧的@State?如果是,那么我如何更改此状态(以及我是否应该尝试更改它?)你是说这就是为什么我会有两个真实来源吗?我已经测试过它,在其他地方它也可以工作,即如果我将一些外部日期传递给init(),然后使用它们初始化@State,并使用State(initialValue:)。然后如果数据在外部来源中刷新,那么init()将再次调用,State(initialValue:)重新初始化,通常正常工作。也有这样的情况,当此外部数据是核心数据管理对象时,必须知道此对象类似于便笺簿,有时我们可以更改它,并认为刷新后它没有正确更新,但它的状态没有使用ManagedObjectContext.rollBack回滚