SwiftUI-@State属性未更新

时间:2020-09-30 14:37:32

标签: swiftui

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

在我的原始应用中,我需要控制多个Sheet。这就是为什么我要enum区分当前活动的工作表并将其存储在@State private var activeSheet中的原因。在@ViewBuilder函数sheetContent()中,返回所选View的{​​{1}}。

对于此测试应用程序,出于简单起见,我仅实现了一张表格。

这是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!")
        }
    }
}

如上面的ContentView代码中所述,class ContentViewSheets { enum State { case aSheet case none } } 属性的值永远不会更改为activeSheet,而是保持.aSheet-这样就会显示错误的工作表。

这是bug还是我不正确理解Apple的.none?他们只是在文档中写明,不得在初始化程序中使用它,而应在@State中使用它,我肯定会这样做。

1 个答案:

答案 0 :(得分:2)

在这种情况下,不要使用两种状态,而要使用一种明确设计的工作表修饰符。

通过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!")
            }
    }
}