SwiftUI - @State 属性未更新

Ulr*_*ich 4 swiftui

自从更新到 Xcode 12 / iOS 14 以来,我遇到了一些奇怪的行为。为了验证此行为,我在测试应用程序中将其隔离。

在我原来的应用程序中,我有多个Sheet要控制的。这就是为什么我必须enum区分当前活动的工作表并将其存储在@State private var activeSheet. 在@ViewBuilder函数中sheetContent(),我返回View所选的Sheet.

对于这个测试应用程序,出于简单原因,我只实现了一张表。

这是 的ContentView代码:

struct ContentView: View {
    @State private var showingSheet = false
    @State private var activeSheet = ContentViewSheets.State.none
    var body: some View {
        Button(action: {
            activeSheet = .aSheet
            showingSheet = true     // <-- ISSUE: activeSheet is still set to .none here!
        }) {
            Text("Open Sheet")
        }
        .sheet(isPresented: $showingSheet, content: sheetContent)
    }
    
    @ViewBuilder
    private func sheetContent() -> some View {
        switch activeSheet {
        case .aSheet:
            Text("I'm the right sheet!")
        case .none:
            Text("Oops! I'm not supposed to show up!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是枚举的代码:

class ContentViewSheets {
    enum State {
        case aSheet
        case none
    }
}
Run Code Online (Sandbox Code Playgroud)

正如上面 ContentView 代码中所注释的,该activeSheet属性的值永远不会更改为.aSheet,而是保留.none- 因此将显示错误的工作表。

这是一个错误还是我没有正确理解苹果的错误@State?他们只是在文档中写道,它不应在初始化程序中使用,而只能在 中使用body,我确实这样做了。

Asp*_*eri 5

对于这种情况,不要使用两种状态,而是使用一种明确设计的图纸修改器。

使用 Xcode 12 / iOS 14 进行测试

class ContentViewSheets {
    enum State: Identifiable {
        case aSheet
        case none

        var id: State { self }
    }
}

struct ContentView: View {
    @State private var activeSheet: ContentViewSheets.State?
    var body: some View {
        Button(action: {
            activeSheet = .aSheet
        }) {
            Text("Open Sheet")
        }
        .sheet(item: $activeSheet) { 
           sheetContent($0) // << activate state passed here !!!
        }
    }

    @ViewBuilder
    private func sheetContent(_ state: ContentViewSheets.State) -> some View {
            switch state {
            case .aSheet:
                Text("I'm the right sheet!")
            default:
                Text("Oops! I'm not supposed to show up!")
            }
    }
}
Run Code Online (Sandbox Code Playgroud)