【问题标题】:SwiftUI clean up ContentViewSwiftUI 清理 ContentView
【发布时间】:2022-02-12 07:10:10
【问题描述】:

我正在尝试简化项目中的 ContentView,但我正在努力了解如何将基于 @State 的逻辑移动到其自己的文件中并使 ContentView 适应任何更改。目前,我有基于@Binding 操作显示自己的动态视图,我将 $binding 向下传递到视图层次结构以使按钮切换布尔值。

这是我目前的尝试。我不确定如何在 SwiftUI 中从嵌套视图更改 SheetPresenter 的视图状态,而无需将 $binding 一直传递到视图堆栈。理想情况下,我希望它看起来像 ContentView.overlay(sheetPresenter($isOpen, $present)

另外,我正在学习 SwiftUI,所以如果这不是最好的方法,请提供指导。

class SheetPresenter: ObservableObject {

@Published var present: Present = .none
@State var isOpen: Bool = false

enum Present {
    case none, login, register
}

@ViewBuilder
func makeView(with presenter: Present) -> some View {
    switch presenter {
    case .none:
        EmptyView()
    case .login:
        BottomSheetView(isOpen: $isOpen, maxHeight: UIConfig.Utils.screenHeight * 0.75) {
            LoginScreen()
        }
    case .register:
        BottomSheetView(isOpen: $isOpen, maxHeight: UIConfig.Utils.screenHeight * 0.75) {
            RegisterScreen()
        }
    }
}

}

【问题讨论】:

  • 如果您不想在视图中一直传递 $binding,您可以在顶视图中创建一个 StateObject 变量并使用 .environmentObject() 传递它。并使用 EnvironmentObject 从任何视图访问它

标签: swiftui state


【解决方案1】:

如果您不想将 $binding 一直传递到视图下方,您可以在顶视图中创建一个 StateObject 变量并使用 .environmentObject() 传递它。并使用 EnvironmentObject 从任何视图访问它

struct testApp: App {
        @StateObject var s1:  sViewModel = sViewModel()
        var body: some Scene {
            WindowGroup {
                ContentView()               
                    .environmentObject(s1)
            }
        }
    }

【讨论】:

  • 我在路径上传递一个 environmentObject 不是一回事吗? - 另外,stateObject 是否允许我改变它的内部工作,如下所示ContentView().Overlay(sViewModel.makeView())
  • 我将此标记为答案,因为它提供了对清理 ContentView() 的正确方法的洞察
  • 我们不使用视图模型对象,这会减慢我们使用 @State 和结构的 SwiftUI。
【解决方案2】:

你是对的,这不是最好的方法,但这是一个常见的错误。在 SwiftUI 中,我们实际上将 @State 用于视图拥有的瞬态数据。这意味着使用像结构这样的值类型,而不是类。这在Data Essentials in SwiftUI from WWDC 2020 中的 4:18 进行了解释。

EditorConfig 可以维护其属性的不变量并进行测试 独立。而且因为 EditorConfig 是一个值类型,所以对 EditorConfig 的一个属性,就像它的进度一样,作为更改可见 到 EditorConfig 本身。

struct EditorConfig {
    var isEditorPresented = false
    var note = ""
    var progress: Double = 0
    mutating func present(initialProgress: Double) {
        progress = initialProgress
        note = ""
        isEditorPresented = true
    }
}
struct BookView: View {
    @State private var editorConfig = EditorConfig()
    func presentEditor() { editorConfig.present(…) }
    var body: some View {
        …
        Button(action: presentEditor) { … }
        …
    }
}

那么您只需使用$editorConfig.isEditorPresented 作为.sheet.overlay 中的布尔绑定即可。

还值得一看 sheet(item:onDismiss:content:),它使显示项目变得更加简单,因为不需要布尔值,它使用可选的 @State,您可以将其设置为 nil 以关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    相关资源
    最近更新 更多