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")
            }
        }
    }
}

Xcode 12.0 beta 2

解决方法

SwiftUI依赖于@State变量,导致body getter在更改时被重新计算。为了使它起作用,body的获取方法必须以一定的方式 depend 依赖于@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)}
    }
}

我们将message更改为Ho,但是在显示工作表时,它仍然显示“嘿”。这是因为没有任何事情可以使body重新计算。您可能会说:Text(message)这个短语呢?是的,但是那是封闭的。它已经被计算,并且message已经被捕获。

要查看我的意思是对的,只需将显示message的文本直接添加到主界面:

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)}
    }
}

现在您的代码可以使用了!当然,我们还在界面中显示了不需要的文本,但要点是,简单而简单的Text(message),而不是 not 足以引起整个{{1 }} body更改时将重新计算getter。因此,我们已经正确解释了您要问的现象。

那么什么是 real 解决方案?如何使message闭包能够按我们期望的那样在的情况下向界面添加额外的Text?一种方法是这样的:

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)} } } ,使message的getter依赖于body变量,现在代码可以按需运行。