SwiftUI `@State`关键字有什么作用?

2hh7jdfx  于 2023-05-05  发布在  Swift
关注(0)|答案(7)|浏览(169)

SwiftUI tutorial使用@State关键字来表示可变的UI状态:
@State var showFavoritesOnly = false
它提供了以下摘要:
状态是一个值或一组值,可以随时间变化,并影响视图的行为、内容或布局。将属性与@State属性一起使用可向视图添加状态。

  • 这个关键字到底是什么意思?
  • 改变@State变量如何导致视图被重新计算?
  • body getter中,其他变量是如何不可变的?
zujrkrfu

zujrkrfu1#

@State关键字是一个@propertyWrapper,这是Swift 5.1中最近引入的一个功能。正如corresponding proposal中所解释的,它是一种避免样板代码的值 Package 器。

  • 旁注:@propertyWrapper以前被称为@propertyDelegate,但此后已更改。请参阅this post了解更多信息。*

official @State documentation有以下内容:
SwiftUI管理您声明为状态的任何属性的存储当状态值发生变化时,视图将使其外观无效,并重新计算主体。将国家作为给定观点的唯一真理来源。

State示例不是值本身;它是阅读和改变值的一种方法。若要访问状态的基础值,请使用其value属性。

因此,当你初始化一个标记为@State的属性时,你实际上并不是在创建自己的变量,而是提示SwiftUI在后台创建 “something” 来存储你设置的内容,并从现在开始监视它!您的@State var只是作为一个委托来访问此 Package 器
每次@State变量被写入时,SwiftUI都会知道它正在监视它。它还将知道@State变量是否是从Viewbody读取的。使用此信息,它将能够**重新计算任何View**在其body中引用了@State变量后更改此变量。

sc4hvdpw

sc4hvdpw2#

如果你了解React Native,我再补充一点。
@State属性非常类似于React Native中的this.state对象。
例如:

struct Foobar: some View {
    @State var username = ""
}
class Foobar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: '',
    };
  }
}

当您修改username变量时,它们将具有相同的效果,即重新呈现当前页面。

sqougxex

sqougxex3#

通过WWDC video - Session 204中的一个例子很好地解释了这一点(从16:00开始,报价从20:15开始)
@State变量的一个特殊属性是SwiftUI可以观察到它们何时被读取和写入。因为SwiftUI知道zoomed是在body中读取的,所以它知道视图的渲染依赖于它。这意味着-当变量更改时,框架将使用新的@State值再次请求body
@State作为属性 Package 器也在Data Flow Through Swift UI(5:38)WWDC视频中进行了详细说明和论证。它展示了当我们需要一个不可变的(structView中的可变值时,它如何解决这个问题。

uwopmtnx

uwopmtnx4#

如果单击@State,可以看到它有几个getter。一个是Value,另一个是Binding<Value>。SwiftUI似乎严重依赖于响应式编程(以及他们的新Combine框架,由于我们无法看到这些 Package 器的完整实现,我希望通过@State属性 Package 器存储的值由Combine中的CurrentValueSubject管理。顾名思义,它本质上存储当前值,然后可以使用$语法将其用作可绑定属性。

0yg35tkg

0yg35tkg5#

注:-接受的答案是正确的,但如果你试图寻找一个更容易的解释,我试着在下面

@State属性 Package 器允许我们在结构体内部更改值。
注意:-结构体中的属性不能更改为值类型,因此不允许更改。

struct ExampleTextView: View {

    // Declare a variable with state property wrapper
    @State private var shouldChangeText: Bool = false
    
    var body: some View {
        Text("Just an example")
            .foregroundColor(Color.white)
    }
}

*如果你想知道我们是否应该添加一个私有访问说明符?

是的,根据经验,苹果建议@State propertise不应该与其他视图共享,因为有更具体的属性 Package 器用于@ObservedObject和@EnvironmentObject。

*但是如果它是值类型,它如何被变异,那么它存储在哪里?

因此,每当我们用@State标记一个属性时,我们都会将其存储从结构体中移出到SwiftUI管理的共享存储中。

如果在你的脑海中,如果你正在与Swift进行比较,这就是它在那里是如何完成的,

struct Example {
    var exampleType: String
    
    mutating func changeType() {
        exampleType = "Are we allowed to do this?"
    }
}

图片来源:请注意,这个答案的灵感来自这篇文章https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper

r8xiu3jd

r8xiu3jd6#

我喜欢斯坦福大学的保罗·赫加蒂教授的解释。他说,@State基本上是将该变量转换为一个指针,指向内存中其他地方的某个布尔值,这就是值发生变化的地方。但是你的变量--现在是一个带有@State的指针--并没有改变,它总是指向内存中的那个地方。

ix0qys7i

ix0qys7i7#

如果你了解C#和Windows开发。@Statex:BindBinding相似(如果不相同)。在集合中,如果不与ObservableCollection相同,则类似。
正如fredpi所说,SwiftUI正在使用@State属性委托列出vars的更新。

相关问题