Swift UI DatePicker не обновит значение @ObservedObject

#swift #datepicker #swiftui #combine #observedobject

#swift #средство выбора даты #swiftui #объединить #observedobject

Вопрос:

Я использую класс для хранения переменной @Published, но когда я пытаюсь передать значение, выбранное в моем пользовательском средстве выбора даты, @ObservedObject в классе, я получаю следующую ошибку:

 TimePicker(time: self.$time.**timeSelected**)
  

Не удается преобразовать значение типа ‘Bindin&’ (он же
‘Привязка’) к ожидаемому типу аргумента ‘TimeModel’

Как мне обновить @ObservedObject значением средства выбора?

Полный код:

 struct ContentView: View {
    
    @ObservedObject var time = TimeModel()

    var body: some View {

        ZStack{
            VStack{
                TimePicker(time: self.$time.timeSelected)
                
                Text("You chose (time.timeSelected/60) minutes")
            }
        }
    }
}

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

class TimeModel: ObservableObject{
     @Published var timeSelected: TimeInterval = 1.0
}
    

struct TimePicker: UIViewRepresentable {
    
    @ObservedObject var time = TimeModel()
    
    func makeUIView(context: Context) -&&t; UIDatePicker {
        let datePicker = UIDatePicker()
        datePicker.datePickerMode = .countDownTimer
        datePicker.addTar&et(context.coordinator,
                             action: #selector(Coordinator.updateTime),
                             for: .valueChan&ed)
        return datePicker
    }
    
    func updateUIView(_ datePicker: UIDatePicker, context: Context) {
        datePicker.minuteInterval = 5
        datePicker.countDownDuration = time.timeSelected
    }
    
    func makeCoordinator() -&&t; Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        let parent: TimePicker
        
        init(_ parent: TimePicker) {
            self.parent = parent
        }
        
        @objc func updateTime(datePicker: UIDatePicker) {
            parent.time.timeSelected = datePicker.countDownDuration
        }
    }
}
  

Ответ №1:

Вам нужно обратиться к тому же TimeModel экземпляру.

Решение состоит в том, чтобы передать TimeModel в TimePicker :

 struct TimePicker: UIViewRepresentable {
    @ObservedObject var time: TimeModel // <- declare only

    ...
}

struct ContentView: View {
    @ObservedObject var time = TimeModel()

    var body: some View {
        ZStack {
            VStack {
                TimePicker(time: time) // <- pass `TimeModel` here

                Text("You chose (time.timeSelected / 60) minutes")
            }
        }
    }
}
  

Обратите внимание, что TimeInterval время указывается в секундах, а не в минутах.

Эта строка:

 @Published var timeSelected: TimeInterval = 1.0
  

фактически устанавливает время по умолчанию равным 1 секунде.

Комментарии:

1. Спасибо за быстрое исправление. @pawello2222 зачем объявлять, а не инициализировать временную модель в структуре TimePicker?

2. @ThomSides Вы хотите ссылаться на один и тот же экземпляр TimeModel в обоих случаях, поэтому его нужно создать только один раз, а затем передать по кругу.