首页 > 解决方案 > 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 测试版 2

标签: swiftswiftui

解决方案


SwiftUI 依赖于导致getter 在更改时重新计算的@State变量。body为此,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)}
    }
}

我们更改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)}
    }
}

现在你的代码可以工作了!当然,我们也在界面中显示了不需要的 Text,但重点是,简单明了Text(message)而不是在闭包中,足以导致整个getter 在更改body时重新计算。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在闭包的捕获列表中,我们使bodygetter 依赖于message变量,现在代码的行为符合预期。


推荐阅读