swiftui 为什么不能分配可选?

Jam*_*ond 3 swift swiftui

为什么不能分配可选?

索引已分配,但仍未显示值

帮帮我,谢谢!

struct TestView: View {
    @State private var index: Int? = nil
    @State private var show: Bool = false
    
    var body: some View {
        VStack {
            Text("Hello, world!")
                .onTapGesture {
                    self.index = 1
                    self.show = true
                    print(self.index as Any)
                }
        }
        .fullScreenCover(isPresented: $show) {
            if let index = self.index {
                Text("value:\(index)")
            } else {
                Text("not value")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Xcode 12.0 测试版 2

mat*_*att 5

SwiftUI 依赖于@State导致bodygetter 在更改时重新计算的变量。为此,bodygetter 必须以某些确定的方式依赖@State变量。您的代码中的问题在于它没有。

为了看到这一点,我们可以将您的代码简化为一个更简单的示例:

struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
        }
        .sheet(isPresented: $show) {Text(message)}
    }
}
Run Code Online (Sandbox Code Playgroud)

我们更改message为 Ho,但是当表出现时,它仍然说 Hey。这是因为没有发生任何事情使body重新计算。你可能会说:那句话Text(message)呢?是的,但那是在闭包中;它已经被计算出来,并且message已经被捕获。

看我说的对不对,message直接在主界面添加一个Text显示即可:

struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
            Text(message)
        }
        .sheet(isPresented: $show) {Text(message)}
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你的代码可以工作了!当然,我们也在界面中显示了不需要的 Text ,但重点是,plain and simple Text(message)而不是在闭包中,足以导致整个bodygetter 在message更改时重新计算。所以我们已经正确解释了您所询问的现象。

那么真正的解决方案是什么?我们如何在向界面添加额外文本的情况下content闭包按预期运行?一种方法是这样的:

struct ContentView: View {
    @State var message = "Hey"
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button("Test") {
                message = "Ho"
                show = true
            }
        }
        .sheet(isPresented: $show) {[message] in Text(message)}
    }
}
Run Code Online (Sandbox Code Playgroud)

通过message在我们的闭包的捕获列表中包含,我们使bodygetter 依赖于message变量,现在代码按预期运行。