gpt4 book ai didi

swift - 如何在 SwiftUI 中的 View 之外制作 State 包装器?

转载 作者:行者123 更新时间:2023-12-04 14:08:24 25 4
gpt4 key购买 nike

我知道 State 包装器是为 View 而设计的,但如果可能的话,我想尝试构建和测试一些代码,我的目标只是为了学习目的,
我的代码有两个大问题!

  • Xcode 找不到 电话 .
  • 如何初始化我的状态?
  • import SwiftUI

    var state: State<T> where T: StringProtocol = State(get: { state }, set: { newValue in state = newValue })

    struct ContentView: View {
    var body: some View {
    Text(state)
    }
    }

    更新:我可以在这里为 Binding 做同样的事情,现在我也想为 State 做同样的事情,并使用向上代码
    import SwiftUI

    var state2: String = String() { didSet { print(state2) } }
    var binding: Binding = Binding.init(get: { state2 }, set: { newValue in state2 = newValue })


    struct ContentView: View {

    var body: some View {

    TextField("Enter your text", text: binding)

    }

    }

    如果我能找到我的问题的答案,我可以在 View 之外定义我的 State 和 Binding,这项工作的 50% 已经完成,它需要另外 50% 的 State Wrapper。

    新更新:
    import SwiftUI

    var state: State<String> = State.init(initialValue: "Hello") { didSet { print(state.wrappedValue) } }
    var binding: Binding = Binding.init(get: { state.wrappedValue }, set: { newValue in state = State(wrappedValue: newValue) })


    struct ContentView: View {

    var body: some View {

    Text(state) // <<: Here is the issue!

    TextField("Enter your text", text: binding)

    }

    }
    enter image description here

    最佳答案

    即使您在 View 外创建了一个 State 包装器, View 如何知道何时刷新其主体?
    如果没有通知 View 的方法,您的代码将执行与以下相同的操作:

    struct ContentView: View {
    var body: some View {
    Text("Hello")
    }
    }
    您接下来可以做什么取决于您想要实现的目标。
    如果您需要的只是一种在 View 之外复制状态行为的方法,我建议您仔细研究组合框架。
    一个有趣的例子是 CurrentValueSubject :
    var state = CurrentValueSubject<String, Never>("state1")
    它存储当前值并充当发布者。
    如果我们在没有观察到任何东西的 View 中使用它会发生什么?
    struct ContentView: View {
    var body: some View {
    Text(state.value)
    .onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    state.value = "state2"
    }
    }
    }
    }
    答案是:没什么。 View 被绘制一次,即使 state更改, View 将不会被重新绘制。
    您需要一种方法来通知 View 有关更改的信息。从理论上讲,您可以执行以下操作:
    var state = CurrentValueSubject<String, Never>("state1")
    struct ContentView: View {
    @State var internalState = ""

    var body: some View {
    Text(internalState)
    .onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    state.value = "state2"
    }
    }
    .onReceive(state) {
    internalState = $0
    }
    }
    }
    但这既不优雅也不干净。在这些情况下,我们可能应该使用 @State :
    struct ContentView: View {
    @State var state = "state1"

    var body: some View {
    Text(state)
    .onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    state = "state2"
    }
    }
    }
    }
    总而言之,如果您需要刷新 View ,只需使用原生 SwiftUI 属性包装器(如 @State )。如果您需要在 View 之外声明状态值,请使用 ObservableObject + @Published .
    否则,有一个巨大的组合框架可以完全满足您的需求。我建议您查看以下链接:
  • Combine: Getting Started
  • Using Combine
  • 关于swift - 如何在 SwiftUI 中的 View 之外制作 State 包装器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66568811/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com