【问题标题】:SwiftUI2, Picker .onChange firing twice need value before change and afterSwiftUI,Picker .onChange 触发两次需要更改前后的值
【发布时间】:2021-06-05 23:48:55
【问题描述】:

我遇到了类似于以下帖子 .onReceive firing twice 的问题。

我有一个可以触发.onChange 两次的选择器。我正在为选择器使用模型数据环境对象。

有没有办法让我获得之前的状态,以便我可以比较 new_haveCount 的值是否真的在变化?或者更好的是,首先防止双火?

@EnvironmentObject var modelData: ModelData

specificsspecificsFirebase 都是结构体。

选择器代码

            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount) ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[1]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount) { _ in
                saveSpecifics()
            }

apple dev page来看,.onChange似乎有一个before andofter属性。

struct PlayerView : View {
var episode: Episode
@State private var playState: PlayState = .paused

var body: some View {
    VStack {
        Text(episode.title)
        Text(episode.showTitle)
        PlayButton(playState: $playState)
    }
    .onChange(of: playState) { [playState] newState in
        model.playStateDidChange(from: playState, to: newState)
    }
}
}

如果有帮助,请查看完整视图

import SwiftUI
import Firebase

struct SpecificsEntryView: View {
@EnvironmentObject var modelData: ModelData

let figure: Figure

var figureIndex: Int {
    modelData.figureArray.firstIndex(where: { $0.id == figure.id })!
}

var body: some View {
    HStack(spacing: 4) {
        // new labels
        VStack(alignment: .leading, spacing: 4) {
            ForEach(kSpecificType_Labels, id: \.self) { label in
                Text(label)
                    .frame(maxHeight: .infinity)
                    .padding(.bottom, 2)
                Divider()
            }
        }
        
        // new values
        VStack(alignment: .center, spacing: 4) {
            Text(kNewText)
                .frame(maxHeight: .infinity)
                .padding(.bottom, 2)
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount) ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[1]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_wantCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.new_wantCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[2]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.new_wantCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_sellCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.new_sellCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[3]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.new_sellCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_orderCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.new_orderCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[4]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.new_orderCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
        } // end new vstack

        Divider() // vertical

        // loose values
        VStack(alignment: .center, spacing: 4) {
            Text(kLooseText)
                .frame(maxHeight: .infinity)
                .padding(.bottom, 2)
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_haveCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_haveCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[1]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_haveCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_wantCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_wantCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[2]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_wantCount) { newVal in
                print("\(modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_wantCount) to \(newVal)")
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            Picker(selection: $modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_sellCount,
                   label: Text("  \(modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_sellCount)  ")) {
                ForEach(0 ..< 20) {
                    Text("\(kSpecificType_Labels[3]) \($0) \(kNewText.lowercased())")
                }
            }
            .onChange(of: modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_sellCount) { _ in
                saveSpecifics()
            }
            .frame(maxHeight: .infinity)
            .padding(.bottom, 2)
            .pickerStyle(MenuPickerStyle())
            Divider()
            TextField("Order from", text: $modelData.figureArray[figureIndex].specifics.specificsFirebase.new_orderText,
                      onCommit: {
                        saveSpecifics()
                      })
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
                .padding(.bottom, 2)
                .background(Color(.systemGray5))
                .cornerRadius(4)
            Divider()
        } // end loose vstack
    } // end all hstack specifics
    .fixedSize(horizontal: false, vertical: true)
    .font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
} // end body

// save specifics on update
func saveSpecifics() {

    // Inject Firebase authentication
    let userID = Auth.auth().currentUser?.uid
    modelData.figureArray[figureIndex].specifics.specificsFirebase.saveSpecifics(userID: userID!)
}
}

【问题讨论】:

  • 您问题的后半部分似乎在回答前半部分——您在从 Apple 开发者页面实现这个想法时遇到问题吗?
  • 共享代码不足以重现问题。
  • 正确,我不知道 [playState] 点 .onChange(of: playState) { [playState] newState in 中的内容。当我输入 modelData.figureArray[figureIndex].specifics.specificsFirebase.new_haveCount 时,我收到一个错误“预期为‘弱’、‘无主’或捕获列表中没有说明符”
  • 如果我执行以下newVal in print("\(modelData.figureArray[figureIndex].specifics.specificsFirebase.loose_wantCount) to \(newVal)") 我得到3 to 3 或任何新值,打印两次。

标签: ios swiftui onchange picker


【解决方案1】:

我遇到了相同的捕获列表语法问题,并通过使用来自 EnvironmentObject 变量的捕获值的显式别名来修复它(Xcode 给出了提示)。像这样:

.onChange(model.someVariable) {[oldValue = model.someVariable] newValue in { ... }

但我的代码仍然导致.onChange 触发两次...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多