使用EnvironmentObject更新SwiftUI滑块

问题描述 投票:0回答:1

我试图通过公共环境对象(输入)获取滑块拇指的位置,以响应来自另一个视图中的文本字段的更改。从滑块到输入再到文本字段,通信工作正常。 TextField 的初始状态通过 .onAppear 修饰符传达给滑块拇指,并且可以正常工作。到目前为止,一切都很好。但是,在 TextField 中所做的后续更改仅显示在滑块中 SliderView 内的文本视图中。这是拇指位置和文本输出不一致的屏幕截图

Inconsistent State

注意拇指的位置。它保持在位置 4,这是它的初始位置。

我将 .onTapGesture 添加到滑块内的文本视图中,并且可以正常工作。拇指移动到与输入一致的位置。这是点击后的

After tapping slider text

我找不到任何修饰符可以强制拇指响应来自文本字段的更改。由于 .onTapGesture 确实有效,我确信滑块可以使用这些信息,只是无法让它自行响应,而且 tapGesture 解决方案看起来很笨拙。我尝试了各种修饰符所有必要的代码如下。看起来环境对象的变化并没有提示滑块更新。


//
//  SliderExample.swift
//  MapTests
//
//  Created by Thomas Mead on 1/20/24.
//
import SwiftUI
import Foundation

struct SliderExample: View {
    @EnvironmentObject var inputs : Inputs
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
        VStack {
            InputView()
            SliderView()
        }
    }
}

struct InputView: View {
    @EnvironmentObject var inputs: Inputs
    var body: some View {
        HStack {
            Text("Sample Number")
            TextField("SampleNumber", value: $inputs.sampleNumber, format: .number)
        }
    }
}

struct SliderView: View {
    @EnvironmentObject var inputs: Inputs
    @State var testNumber = 1.0
    var body: some View {
        HStack {
            Slider(value: $testNumber, in: 1...20.0, step: 1.0)
              .onChange(of: testNumber, perform: {data in inputs.sampleNumber =        Int(testNumber)} )
            .onAppear() {testNumber = Double(inputs.sampleNumber)}
        
            Text("Sample \(Int(inputs.sampleNumber))")
                .onTapGesture {
                    testNumber = Double(inputs.sampleNumber)
                }
            }
        }
    }

class Inputs: Observable, ObservableObject {
    init() {
    }
        @Published var sampleNumber: Int = 4
}


#Preview {
    SliderExample()
}
swiftui view slider modifier
1个回答
0
投票

您的

Slider
不更新的原因是因为您没有更新
testNumber
当模型的
sampleNumber
发生变化时。

尝试在您的

.onChange()
 中使用 
SliderView

来尝试此方法

注意,您不应该拥有

Observable
以及
ObservableObject in your 
类输入`。

struct ContentView: View {
    @StateObject var inputs = Inputs()
    
    var body: some View {
        SliderExample()
            .environmentObject(inputs)
    }
}

struct SliderExample: View {
    @EnvironmentObject var inputs : Inputs
    
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
        VStack {
            InputView().border(.red)
            SliderView()
        }
    }
}

struct InputView: View {
    @EnvironmentObject var inputs: Inputs
    
    var body: some View {
        HStack {
            Text("Sample Number")
            TextField("SampleNumber", value: $inputs.sampleNumber, format: .number)
        }
    }
}

struct SliderView: View {
    @EnvironmentObject var inputs: Inputs
    @State var testNumber = 1.0
    
    var body: some View {
        HStack {
            Slider(value: $testNumber, in: 1...20.0, step: 1.0)
                .onChange(of: testNumber) {  // <--- here
                    inputs.sampleNumber = Int(testNumber)
                }
                .onAppear() {
                    testNumber = Double(inputs.sampleNumber)
                }
            
            Text("Sample \(Int(inputs.sampleNumber))")
                .onTapGesture {
                    testNumber = Double(inputs.sampleNumber)
                }
        }
        .onChange(of: inputs.sampleNumber) {  // <--- here
            testNumber = Double(inputs.sampleNumber)
        }
    }
}

class Inputs: ObservableObject { // <-- here  no  Observable,
    @Published var sampleNumber: Int = 4
}
© www.soinside.com 2019 - 2024. All rights reserved.