在SwiftUI中更新其他变量时如何修改/重置@State [英] How to modify/reset @State when other variables are updated in SwiftUI

查看:714
本文介绍了在SwiftUI中更新其他变量时如何修改/重置@State的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每次@ObservedObject被重新分配"时,我想重设一些@State.如何做到这一点?

I would like to reset some @State each time an @ObservedObject is "reassigned". How can this be accomplished?


class Selection: ObservableObject {
    let id = UUID()
}

struct ContentView: View {
  @State var selectedIndex: Int = 0
  var selections: [Selection] = [Selection(), Selection(), Selection()]
  var body: some View {
        VStack {
            // Assume the user can select something so selectedIndex changes all the time
            // SwiftUI will just keep updating the same presentation layer with new data
            Button("Next") {
                self.selectedIndex += 1
                if self.selectedIndex >= self.selections.count {
                    self.selectedIndex = 0
                }
            }
            SelectionDisplayer(selection: self.selections[self.selectedIndex])
        }
  }
}

struct SelectionDisplayer: View {
    @ObservedObject var selection: Selection {
        didSet { // Wish there were something *like* this
            print("will never happen")
            self.tabIndex = 0
        }
    }

  @State var tapCount: Int = 0 // Reset this to 0 when `selection` changes from one object to another

  var body: some View {
        Text(self.selection.id.description)
            .onReceive(self.selection.objectWillChange) {
                print("will never happen")
        }
        Button("Tap Count: \(self.tapCount)") {
            self.tapCount += 1
        }
    }
}

我知道了onReceive,但是我不是想响应objectWillChange来修改状态,而是当对象本身被关闭时.在具有引用类型的UIKit中,我将使用didSet,但这在这里不起作用.

I'm aware of onReceive but I'm not looking to modify state in response to objectWillChange but rather when the object itself is switched out. In UIKit with reference types I would use didSet but that doesn't work here.

我确实尝试为此使用PreferenceKey(要点),但看起来像太多了.

I did try using a PreferenceKey for this (gist) but it seems like too much of a hack.

推荐答案

当前(测试版5),最好的方法可能是对数据要更改时要重置的项目使用构造函数以及通用的ObservableObject.这样可以保留一些@State,而有些则被重置.

Currently (Beta 5), the best way may be to use the constructor plus a generic ObservableObject for items that I want to reset when the data changes. This allows some @State to be preserved, while some is reset.

在下面的示例中,每次selection更改时,tapCount都会重置,而allTimeTaps不变.

In the example below, tapCount is reset each time selection changes, while allTimeTaps is not.

class StateHolder<Value>: ObservableObject {
    @Published var value: Value
    init(value: Value) {
        self.value = value
    }
}

struct ContentView: View {

  @State var selectedIndex: Int = 0
  var selections: [Selection] = [Selection(), Selection(), Selection()]
  var body: some View {
        VStack {
            // Assume the user can select something so selectedIndex changes all the time
            // SwiftUI will just keep updating the same presentation though
            Button("Next") {
                self.selectedIndex += 1
                if self.selectedIndex >= self.selections.count {
                    self.selectedIndex = 0
                }
            }
            SelectionDisplayer(selection: self.selections[self.selectedIndex])
        }
  }
}

struct SelectionDisplayer: View {

    struct SelectionState {
        var tapCount: Int = 0
    }

    @ObservedObject var selection: Selection
    @ObservedObject var stateHolder: StateHolder<SelectionState>
    @State var allTimeTaps: Int = 0

    init(selection: Selection) {
        let state = SelectionState()
        self.stateHolder = StateHolder(value: state)
        self.selection = selection
    }

  var body: some View {
        VStack {
            Text(self.selection.id.description)
            Text("All Time Taps: \(self.allTimeTaps)")
            Text("Tap Count: \(self.stateHolder.value.tapCount)")
            Button("Tap") {
                self.stateHolder.value.tapCount += 1
                self.allTimeTaps += 1
            }
        }
    }
}

在寻找解决方案时,我很感兴趣地发现您无法在init中初始化@State变量.编译器会抱怨在访问self之前尚未设置所有属性.

While looking for a solution I was quite interested to discover that you cannot initialize @State variables in init. The compiler will complain that all properties have not yet been set before accessing self.

这篇关于在SwiftUI中更新其他变量时如何修改/重置@State的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆