我创建了一个这样的模型
import Foundation
class Play:ObservableObject{
@Published var name:String="Tayle"
@Published var age:Int=12
}
它将在两个视图中使用
例如:
struct Demo: View {
//1
@State private var play:Play = Play()
//2
//@StateObject private var play:Play = Play()
var body: some View {
NavigationView{
NavigationLink(destination: PlayNameView(play: play)){
Text("go to platnbame")
}
}
}
}
struct PlayNameView:View{
@ObservedObject var play:Play
var body: some View{
HStack{
Text("Hello,\(play.name)")
Button(action:{
play.name="iop"
}){
Text("change the name to:iop")
}
}
}
}
当我运行该项目时,他们有相同的行为。如果@StateObject可以做到,为什么还要选择@State
@State
是一个变量,用于保存值类型,例如布尔值、整数、字符串、结构体等。苹果根本不打算@State
用于引用类型,例如ObservableObjects
,因为 State 再次意味着存储 Int 等值类型,而不是类的实例。苹果在文档中表示,
不要将状态属性用于持久存储,因为状态变量的生命周期反映了视图生命周期。相反,使用它们来管理仅影响用户界面的瞬态,例如按钮的突出显示状态、过滤器设置或当前选定的列表项。
简而言之,你可以使用@State
例如,用于存储用户单击按钮的次数(自应用程序启动以来)的变量,但不存储另一个按钮ObservableObject
。另外,如果你看一下this,文章表明使用带有状态的对象不会导致视图的实际变量更新。这是因为,再次引用这篇文章,
因为我们使用的是复杂的引用类型,所以状态本身的值永远不会改变。虽然 state 的属性 num 已更改,但 @State 属性包装器不知道,因为它只监视变量状态,而不监视其任何属性。对于 SwiftUI 来说,因为它只是观察状态,所以它不知道 num 已经改变,所以永远不会重新渲染视图。
An @StateObject
另一方面,可以存储诸如ObservableObjects
。当Object的值发生变化时,会引起视图更新,因为这一切都是由SwiftUI
。这只会发生在@Published
但是,属性以及这些属性的任何更改都将再次导致视图重新渲染。还有一个重要的注意事项:@StateObject
每次视图出现时都会创建一个新实例。如果需要保留这些值,则需要从更根的视图传入对象。另外,一个@StateObject
可以从视图外部更改,而@State
变量只能是私有的和局部的。有关其原因的更多信息,请参阅 AppleState
文档:https://developer.apple.com/documentation/swiftui/state
资源:
- https://story.tomasen.org/swiftui-difference-of-state-binding-environment-and-environmentobject-and-when-to-use-them-ff80699f45b7
- https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-stateobject-property-wrapper
- https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference- Between-observedobject-state-and-environmentobject
-
https://levelup.gitconnected.com/state-vs-stateobject-vs-observedobject-vs-environmentobject-in-swiftui-81e2913d63f9#:~:text=Use%20%40%20State%20for%20very%20simple,比%20what%20%40State%20can%20handle.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)