【问题标题】:SwiftUI: 'self' used before all stored properties are initializedSwiftUI:在初始化所有存储的属性之前使用“自我”
【发布时间】:2020-11-14 21:36:19
【问题描述】:

是的,我知道以前有人问过这个问题,但接受的答案对我不起作用。这些答案确实修复了编译器错误,但是当我从 ContentView.init 方法中将“self”传递给类的初始化程序,并且该类稍后调用 ContentView 上的方法时,“self”不是正确的实例。回调 setVpnState 设置 @State 变量的值,这应该会导致 UI 更新。但事实并非如此,并且在 lldb 中检查时,它显然不是同一个“自我”(ContentView 的实例)。

这是我最初尝试做的:

struct ContentView: View {
    
    let iwinsController: IWiNSController

    init() {
        iwinsController = IWiNSController(view: self)
    }

    var body: some View {
        .
        .
        .
    }
        
    func setVpnState(_ state: ButtonState) {
        self.buttonAttributes = buttonConfig[state]!
    }
}

如你所料,我得到的错误是'self' used before all stored properties are initialized

然后我尝试了这个问题的两个答案:'self' used before all stored properties are initialized

这确实满足了编译器,但正如我所说,当从我的控制器对象调用 setVpnState 时,'self' 不正确。

所以,我要做的是在不传递“self”的情况下初始化我的控制器,然后在 onAppear 中明确设置视图。这行得通。但这意味着在我的控制器中,我每次使用它时都必须打开 view

感觉不是很“敏捷”。我是 Swift 的新手,希望以公认的方式来做这件事。

struct ContentView: View {

    let iwinsController: IWiNSController

    init() {
       self.iwinsController = IWiNSController()
    }

    var body: some View {
        .
        .
        .
        }.onAppear {
            iwinsController.setView(view: self)
        }
    }
    
    func setVpnState(_ state: ButtonState) {
        self.buttonAttributes = buttonConfig[state]!
    }
}

【问题讨论】:

  • 将 'self' 传递给类的初始化程序 ...您从类的角度思考,但 SwiftUI 视图是 结构 - 值类型- 没有参考。这个iwinsController.setView(view: self) 只是复制了self.... 你需要改变对 SwiftUI 的看法。

标签: swiftui initialization


【解决方案1】:

如果我正确理解了这个问题,听起来您希望视图从您的视图中跟踪一些 vpnState 类,并且您正试图将视图中的引用传递给控制器​​对象,但这与 SwiftUI 的设计方式背道而驰.

从根本上说,您应该将视图视为只读对象,这些对象由框架在幕后更新。您将它们锁定到要观察的属性或对象上,当该事物发生变化时,视图会自动更新为新值。

@State 变量旨在严格在您的视图内使用,例如用于动画或完全在视图内的其他中间状态。在这种情况下,Swifty 要做的事情是使用 @ObservedObject@EnvironmentObject 为您监视对象的状态。

为什么self 在你使用它时是一个“不同”的对象,因为struct 是一个值类型而不是一个引用类型。每次更改时,它都会被 Swift 销毁和重新创建。在对象上更改值的意义上,它不是“更新”的。

【讨论】:

  • Asperi 也是这么说的。将self 传递给值类型的对象只会复制不会影响原始对象的对象。
  • 非常感谢,我需要改变我的思维方式,但是,@Joshua - 为什么当我在控制器上调用“setView”时它会起作用?如果它正在制作副本,为什么 setVpnState 现在可以工作?
  • 更合适的方法是使用通知中心并从我的控制器对象发送通知吗?我的意图是从应用程序的机制中整理视图 - 让 ContentView 只是一个 UI。但是状态需要受到应用程序其他部分的影响。
  • 好的,刚刚查看了@ObservedObject 并将状态信息存储在一个单独的类中,所以我会接受这个答案
  • 您的函数正在对象中使用 self。它不会在任何地方传递它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-01
  • 2020-11-23
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 2018-09-09
相关资源
最近更新 更多