@State 和 @StateObject 有什么区别

zhe*_*ang 7 ios swift swiftui

我创建了一个这样的模型

import Foundation

class Play:ObservableObject{
    @Published var name:String="Tayle"
    @Published var age:Int=12
}
Run Code Online (Sandbox Code Playgroud)

它将在两个视图中使用

例如:

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")
            }
            
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行该项目时,他们有相同的行为。如果@StateObject可以做到,为什么还要选择@State

小智 17

@State是一个变量,用于保存值类型,例如布尔值、整数、字符串、结构体等。Apple 根本不打算用于@State诸如 之类的引用类型ObservableObjects,因为 State 再次意味着存储诸如 Int 之类的值类型,而不是类的实例。苹果在文档中表示,

\n
\n

不要\xe2\x80\x99t 使用状态属性进行持久存储,因为状态变量的生命周期反映了视图生命周期。相反,使用它们来管理仅影响用户界面的瞬态,例如按钮的突出显示状态、过滤器设置或当前选定的列表项。

\n
\n

简而言之,您可以使用@State变量来存储用户单击按钮的次数(自应用程序启动以来),但不能存储另一个ObservableObject. 另外,如果您查看此文章,文章显示使用带有状态的对象不会导致视图的实际变量更新。这是因为,再次引用这篇文章,

\n
\n

因为我们\xe2\x80\x99使用的是复杂的引用类型,所以状态本身的值永远不会改变。虽然 state 的属性 num 已更改,但 @State 属性包装器不知道,因为它只监视变量状态,而不监视其任何属性。对于 SwiftUI 来说,因为它只是观察状态,所以它不知道 num 已经改变,所以永远不会重新渲染视图。

\n
\n

@StateObject另一方面,An可以存储诸如 之类的东西ObservableObjects。当Object的值发生变化时,会引起视图更新,因为所有这些都被观察到SwiftUI。不过,这种情况只会发生在@Published属性上,并且这些属性的任何更改都将再次导致视图重新渲染。还有一个重要的注意事项:@StateObject每次视图出现时都会创建一个新实例。如果需要保留这些值,则需要从更根的视图传入对象。此外,@StateObject可以从视图外部更改 an ,而@State变量只能是私有的和本地的。有关原因的更多信息,请参阅 AppleState文档:https ://developer.apple.com/documentation/swiftui/state

\n

资源:

\n
    \n
  1. https://story.tomasen.org/swiftui-difference-of-state-binding-environment-and-environmentobject-and-when-to-use-them-ff80699f45b7
  2. \n
  3. https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-stateobject-property-wrapper
  4. \n
  5. https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference- Between-observedobject-state-and-environmentobject
  6. \n
  7. 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
  8. \n
\n


Uma*_*han 6

对于对象,请使用@StateObject属性包装器。对于 String、Int 等,请使用@State属性包装器。

@State:当我们观察 ContentView 中存在的属性时,我们使用此属性包装器。

@StateObject:当我们观察 ContentView 外部(如对象中)的属性时,我们使用此属性包装器,我们可以通过首先使该类符合ObservableObject协议并将该属性标记为@Published对象内部来观察属性的变化。

  • 不,等等,那是不对的,当 View 拥有该对象时,应该使用 @StateObject...您描述的情况应该由 @ObservedObject 处理 (3认同)