SwiftUI 中 init() 内部的条件

Conditions inside init() in SwiftUI

我需要将 init 与 SwiftUI 一起使用,但我只是在学习初始化程序。找了很多复杂的例子,但是基本都看不懂

如何根据其他一些变量的值在 init() 中初始化不同的值,例如基于来自切换的 true/false?

示例代码

我正在尝试这样的事情:

import SwiftUI

struct ToggleView: View {
    
    @State var toggleValue: Bool = true
    
    var testValue: String
    
    init() {
        if toggleValue {
            self.testValue = "true"
        } else {
            self.testValue = "false"
        }
    }
    
    var body: some View {
        
        VStack {
            Toggle(isOn: $toggleValue) {
                Text("True or false?")
            }.padding()
            
            Text("Selected value:")
            Text("\(testValue)")
        }
    }
}

struct ToggleView_Previews: PreviewProvider {
    static var previews: some View {
        ToggleView()
    }
}

但是与 if toggleValue { 一致,我得到一个错误:

'self' used before all stored properties are initialized

我试过改变:

var testValue: String

init() {

至:

@Binding var testValue: String

init(testValue: Binding<String>) {

但是也没用。如何将此 testValue 与切换绑定,因此在点击切换后我的应用程序将打印:“Selected value: false”?

TLDR;您永远不能用另一个存储的 属性 初始化一个存储的 属性。如果您想用相同的值初始化两个属性,该值必须来自初始化程序中的参数或某个常量。


编译器实际上给出了一个非常有用的错误。在使用 self 之前,需要初始化所有存储的属性。在您的示例中,您有两个存储属性:toggleValuetestValuetoggleValue 已初始化,但 testValue 未初始化。由于读取存储的 属性 是 using self 的示例,因此您 不能 使用存储的 属性 来初始化另一个存储的 属性。您 可以 使用 init().

中的参数初始化属性

例如:

init(initialValue: Bool) {
    testValue = initialValue ? "true" : "false"
}

或者您可以使 testValue 成为依赖于另一个 属性:

的计算 属性
var testValue: String {
    toggleValue ? "true" : "false"
}

如果你想保持 testValuetoggleValue 同步 能够修改 testValue 你可以使用绑定:

var testValue: Binding<String> { 
    Binding<String>(
        get: { toggleValue ? "true" : "false" },
        set: { toggleValue = [=12=] == "true" }
    )
}

如果你只想初始化 testValue in sync with toggleValue 你可以使用静态常量:

static let initialValue = true
@State var toggleValue = ToggleView.initialValue
var testValue = ToggleView.initialValue ? "true" : "false"

或者在初始化器中使用常量:

init() {
    let initialValue = true
    toggleValue = initialValue
    testValue = initialValue ? "true" : "false"
    // Note that in this case the compiler will inform you the 'false'
    // branch will never be executed (which is correct). To prevent this
    // you can either depend on a static constant, create your own
    // extension on bool to provide a string, or just use:
    // testValue = "\(initialValue)"
}

请注意,结构有一个隐式初始化程序,它存储按出现顺序列出的属性。使用初始化属性作为可选参数。这意味着您可以通过以下方式初始化 ToggleView(无需指定初始化程序):

ToggleView(toggleValue: false, testValue: true)
ToggleView(testValue: true)