在 SwiftUI 中使用 @State 属性包装器未更新视图
Posted
技术标签:
【中文标题】在 SwiftUI 中使用 @State 属性包装器未更新视图【英文标题】:View is not updated using @State property wrapper in SwiftUI 【发布时间】:2020-05-04 19:44:00 【问题描述】:使用@State 包装器不会更新视图。 视图在不使用 @State 包装器的情况下更新,但必须手动进行。
import SwiftUI
struct SwiftUIView: View
@ObservedObject var people: People
var body: some View
VStack
ForEach(people.peoples) person in
HStack
Text("\(person.age)")
if person.ismale
Text("Male")
else
Text("Female")
Button(action: person.age += 1)
Text("Age+1")
struct Person: Identifiable
var id = UUID()
@State var age: Int
var ismale = true
class People: ObservableObject
@Published var peoples: [Person]
init()
self.peoples = [
Person(age: 10),
Person(age: 12, ismale: false)
]
struct SwiftUIView_Previews: PreviewProvider
static var previews: some View
SwiftUIView(people: People())
由于某种原因,单击按钮时,视图没有变化。
如果我把它改成
Button(action: **self.people.peoples[0].age += 1** )
Text("Age+1")
...
struct Person: Identifiable
var id = UUID()
**var age: Int**
var ismale = true
它会更新,但按钮不会是动态的。但是,如果我在 ForEach 循环中执行 person.age += 1
而不使用 @State
变量年龄包装器。
错误:“变异运算符的左侧不可变:'person' 是 'let' 常量”
我以为我理解 Struct、Class、@State 的含义……我想不明白……感谢您提供任何解决方案。
【问题讨论】:
【参考方案1】:struct
通过引用传递,因此您不需要 @State
,因为 ObservableObject
已经收到更新。
这是Person
结构
struct Person: Identifiable
var id = UUID()
var age: Int
var ismale = true
还有SwiftUIView
。我删除了If
语句,因此代码更简洁。
ForEach(people.peoples.indices, id: \.self) index in
HStack
Text("\(self.people.peoples[index].age)")
Text(self.people.peoples[index].ismale ? "Male" : "Female")
Button(action: self.people.peoples[index].age += 1 )
Text("Age+1")
【讨论】:
感谢您的解决方案。我真的不明白为什么person.age += 1
在 ForEach 循环中不起作用并输出错误:“变异运算符的左侧不可变:'person' 是 'let' 常量”。你能指出我正确的方向吗?谢谢!
它不起作用,因为在ForEach
循环中,person
是一个常量,不能修改。一般来说,闭包值是一个常数。以上是关于在 SwiftUI 中使用 @State 属性包装器未更新视图的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中用另一个 @State 属性值初始化 @State 属性
深度解析:为何在 SwiftUI 视图的 init 初始化器里无法更改 @State 的值?
深度解析:为何在 SwiftUI 视图的 init 初始化器里无法更改 @State 的值?
SwiftUI之深入解析@StateObject@ObservedObject和@EnvironmentObject的联系和区别