【问题标题】:Difference between struct and class in Swift, also SwiftUI not updatingSwift中结构和类之间的区别,SwiftUI也没有更新
【发布时间】:2021-10-17 12:28:52
【问题描述】:

我遇到了一些问题并写了一些基本的变体来显示问题:

import SwiftUI

struct PersonStruct {
    // Requires @State because self.name is immutable otherwise
    @State var name:String

    init (_ name: String) { self.name = name }
    
    func changeName(_ name: String) {
        self.name = name
        print (self.name)
    }
}

class PersonClass {
    var name:String

    init (_ name: String) { self.name = name }
    
    func changeName(_ name: String) {
        self.name = name
        print (self.name)
    }
}

struct ContentView: View {
    var person1:PersonStruct = PersonStruct("Peter S.")
    var person2:PersonClass = PersonClass("Peter C.")

    var body: some View {
        VStack {
            Text(person1.name)
            .padding()
            Text(person2.name)
            .padding()
            
            Button("Change name") {
                person1.changeName("Trevor")
                person1.name = "Trevor"

                person2.changeName("Trevor")
                person2.name = "Trevor"

                print("---")
                print (person1.name)
                print (person2.name)
            }
            .padding()
        }
        .font(.title)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

person 变量的行为不同,按下按钮将 person2 的名称从“Peter C”更改为 Trever - 如控制台中的“print”所示。 但是 person1 的名字不会改变,它保持在“Peter S”。 ...

因此,该结构似乎根本不起作用。

在这两种情况下,视图中的文本输出都不会改变 - “Peter C”和“Peter S”保持可见。

为什么 person1 的内容没有改变? 我什至使用了函数“changeName()”,还尝试直接设置名称。 无济于事:-(

【问题讨论】:

  • 您不应在非 SwiftUI 结构中使用 @State,即不符合 View 的结构。另一方面,您应该将@State 用于ContentView 中的两个属性。如果您仍有问题,请修复并返回
  • 删除结构中的@State 给出了“无法分配给属性:'self' 是不可变的”,如上所述。但是 vadian 的“变异”确实解决了这个问题!

标签: swift class struct swiftui


【解决方案1】:

首先它要求struct中的name标有@State,其实反正是错的,只要把函数设为mutating就行了

struct PersonStruct {
    var name : String

    init (_ name: String) { self.name = name }
    
    mutating func changeName(_ name: String) {
        self.name = name
        print (self.name)
    }
}

为了能够观察类采用ObservableObject并添加属性包装器@Published

class PersonClass : ObservableObject {
    @Published var name:String

    init (_ name: String) { self.name = name }
    
    func changeName(_ name: String) {
        self.name = name
        print (self.name)
    }
}

在视图中将结构声明为@State,将类声明为@StateObject

@State private var person1 = PersonStruct("Peter S.")
@StateObject private var person2 = PersonClass("Peter C.")

【讨论】:

  • 这就像一个魅力,非常感谢!使用“@State”而不是“@StateObject”似乎也适用于 person2 ...
  • 规则是:@State 用于值类型,@StateObject 用于引用类型。
猜你喜欢
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-26
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
  • 2019-03-07
相关资源
最近更新 更多