изменение содержимого TextField

Добрый день! Недавно начал изучать SwiftUI, и столкнулся с проблемой. Начал делать конвертер величин. Хочу сделать так, чтобы при вводе значения в одно из TextField - текст в остальных TextField менялся Прошу подсказки)

Canvas

import SwiftUI
import Combine

struct ContentView: View {
    @State var celsius: String = ""
    @State var kelvin: String = ""
    @State var farenheit: String = ""
    @State var reyumur: String = ""
    @State var rankin: String = ""
    var body: some View {
        NavigationView {
            Temperature(celsius: $celsius, kelvin: $kelvin, farenheit: $farenheit, reyumur: $reyumur, rankin: $rankin)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Temperature: View {
    @Binding var celsius: String
    @Binding var kelvin: String
    @Binding var farenheit: String
    @Binding var reyumur: String
    @Binding var rankin: String
    var body: some View {
        List {
            Section(
                header: Text("Международная система (СИ)")) {
                HStack {
                    TextField("Введите значение", text: $celsius)
                        .keyboardType(.numbersAndPunctuation)
                        .onReceive(Just(celsius)) { newValue in
                            let filtered = newValue.filter { "0123456789.".contains($0) }
                            if filtered != newValue {
                                self.celsius = filtered
                            }
                        }
                    Text("°C")
                        .padding(.horizontal)
                        .font(.headline)
                        .foregroundColor(.blue)
                }
                HStack {
                    TextField("Введите значение", text: $kelvin)
                        .keyboardType(.numbersAndPunctuation)
                        .onReceive(Just(kelvin)) { newValue in
                            let filtered = newValue.filter { "0123456789.".contains($0) }
                            if filtered != newValue {
                                self.kelvin = filtered
                            }
                        }
                    Text("K")
                        .padding(.horizontal)
                        .font(.headline)
                        .foregroundColor(.blue)
                }
            }
            Section(
                header: Text("США и Британия")) {
                HStack {
                    TextField("Введите значение" , text: $farenheit)
                        .keyboardType(.numbersAndPunctuation)
                        .onReceive(Just(farenheit)) { newValue in
                            let filtered = newValue.filter { "0123456789.".contains($0) }
                            if filtered != newValue {
                                self.farenheit = filtered
                            }
                        }
                    Text("F")
                        .padding(.horizontal)
                        .font(.headline)
                        .foregroundColor(.blue)
                }
            }
            Section(
                header: Text("Редкоиспользуемые")) {
                HStack {
                    TextField("Введите значение" , text: $reyumur)
                        .keyboardType(.numbersAndPunctuation)
                        .onReceive(Just(reyumur)) { newValue in
                            let filtered = newValue.filter { "0123456789.".contains($0) }
                            if filtered != newValue {
                                self.reyumur = filtered
                            }
                        }
                    Text("Re")
                        .padding(.horizontal)
                        .font(.headline)
                        .foregroundColor(.blue)
                }
                HStack {
                    TextField("Введите значение" , text: $rankin)
                        .keyboardType(.numbersAndPunctuation)
                        .onReceive(Just(rankin)) { newValue in
                            let filtered = newValue.filter { "0123456789.".contains($0) }
                            if filtered != newValue {
                                self.rankin = filtered
                            }
                        }
                    Text("R")
                        .padding(.horizontal)
                        .font(.headline)
                        .foregroundColor(.blue)
                }
            }
        }
        .navigationBarTitle("Температура")
        .navigationBarTitleDisplayMode(.inline)
    }
}

Ответы (1 шт):

Автор решения: Andrew

В даном случае тебе желательно все сделать через модель.

Это делается как-то так:

public class TemperatureViewModel: ObservableObject {
    var blockedChanges = false
 
    @Published var celsius: String { didSet { celsiusChanged() } }
    @Published var kelvin: String { didSet { kelvinChanged() } }
    @Published var farenheit: String { didSet { farenheitChanged() } }
    @Published var reyumur: String { didSet { reyumurChanged() } }
    @Published var rankin: String { didSet { rankinChanged() } }


    func celsiusChanged() {
        if self.blockedChanges == true { return }
        self.blockedChanges = true
       
        //здесь меняй все переменные

        self.blockedChanges = false
    }

    func kelvinChanged() {
        if self.blockedChanges == true { return }
        self.blockedChanges = true
       
        //здесь меняй все переменные

        self.blockedChanges = false
    }

    func farenheitChanged() {
        if self.blockedChanges == true { return }
        self.blockedChanges = true
       
        //здесь меняй все переменные

        self.blockedChanges = false
    }

    func reyumurChanged() {
        if self.blockedChanges == true { return }
        self.blockedChanges = true
       
        //здесь меняй все переменные

        self.blockedChanges = false
    }

    func rankinChanged() {
        if self.blockedChanges == true { return }
        self.blockedChanges = true
       
        //здесь меняй все переменные

        self.blockedChanges = false
    }
}

твою вьюху полностью изменять не буду, только главное:

struct ContentView: View {
    var temperatureVm = TemperatureViewModel()

    var body: some View {
        NavigationView {
            Temperature(model: temperatureVm)
        }
        
    }
}

struct Temperature: View {
    @ObservedObject model

    var body: some View {
        List {
   .......
}

остальное поменяй сам


флаг blockedChanges необходим что бы твоя программа не ушла в вечный цикл.

еще желательно ознакомится с вот этим: https://stackoverflow.com/questions/56561630/swiftui-forcing-an-update/62919526#62919526

→ Ссылка