如何使用SwiftUI和Combine检测Datepicker的值变化? [英] How to detect a value change of a Datepicker using SwiftUI and Combine?

查看:165
本文介绍了如何使用SwiftUI和Combine检测Datepicker的值变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用SwiftUI和Combine时如何检测Datepicker的值变化?
每当日期选择轮移动时,我都需要调用一个方法,以更新文本和滑块。

How would you detect a change of value of a Datepicker while using SwiftUI and Combine? I need to invoke a method whenever the datepicker wheel is moved, to update a Text and a Slider.

我一直在寻找可以识别值的特定方法更改(使用UIKit可以将动作与事件相关联),但是显然我在文档中没有找到任何有用的东西(我已经尝试过onTapGesture方法,但这不是我想要的,因为它迫使用户点击选择器以更新其他视图,而我希望每当用户移动方向盘时都进行自动更新。)

I have looked for specific methods to identify the value change (using UIKit it was possible to associate an action to an event), but apparently I haven't found anything useful in the documentation (I've tried the onTapGesture methods, but that's not what I want, since it forces the user to tap the picker to update the other views, whereas I would like to have an automatic update whenever the user moves the wheel).

import SwiftUI

struct ContentView: View {

    private var calendar = Calendar.current

    @State private var date = Date()
    @State private var weekOfYear = Double(Calendar.current.component(.weekOfYear, from: Date()) )
    @State private var lastWeekOfThisYear = 53.0
    @State private var weekDay: String = { () -> String in 
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEEE"
        let weekDay = dateFormatter.string(from: Date())
        return weekDay
    }()

    var body: some View {

        VStack {

            // Date Picker
            DatePicker(selection: $date, displayedComponents: .date, label:{ Text("Please enter a date") }
            )
            .labelsHidden()
            .datePickerStyle(WheelDatePickerStyle())
            .onTapGesture {
                self.updateWeekAndDayFromDate()
            }

            // Week number and day
            Text("Week \(Int(weekOfYear.rounded()))")
            Text("\(weekDay)")

            // Slider
            Slider(value: $weekOfYear, in: 1...lastWeekOfThisYear, onEditingChanged: { _ in
                    self.updateDateFromWeek()
                })
            }

    }

    func updateWeekAndDayFromDate() {
        // To do
    }

    func updateDateFromWeek() {
        // To do
    }

    func setToday() {
        // To do
    }

    func getWeekDay(_ date: Date) -> String {
        //To do
    }
}

I猜想可以使用Combine(可以观察到的对象,已发布,接收器等)解决此问题,但是我尚不具备使用Combine的经验,因此我想寻求帮助...有什么想法吗? :)

I guess this could be solved using Combine (observableobject, published, sink, etc.), but I'm not experienced yet with Combine, therefore I'd like to ask for some help... any ideas? :)

非常感谢!

推荐答案

请在下面找到一个可能的方法(稍微修改一下代码)。这是使源状态透明以激活其中的依赖关系的想法。希望对您有所帮助。

Please find below one possible approach (with a bit modified your code). Here is an idea to have source state transparent to activate dependent within it. Hope it will be helpful somehow.

此处为演示

这里是代码

struct TestDatePicker: View {

    private static func weekOfYear(for date: Date) -> Double {
        Double(Calendar.current.component(.weekOfYear, from: date))
    }

    private static func weekDay(for date: Date) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEEE"
        let weekDay = dateFormatter.string(from: date)
        return weekDay
    }

    @State private var date: Date
    @State private var weekOfYear: Double
    @State private var weekDay: String
    @State private var lastWeekOfThisYear = 53.0

    private var dateProxy:Binding<Date> {
        Binding<Date>(get: {self.date }, set: {
            self.date = $0
            self.updateWeekAndDayFromDate()
        })
    }

    init() {
        let now = Date()
        self._date = State<Date>(initialValue: now)
        self._weekOfYear = State<Double>(initialValue: Self.weekOfYear(for: now))
        self._weekDay = State<String>(initialValue: Self.weekDay(for: now))
    }

    var body: some View {

        VStack {

            // Date Picker
            DatePicker(selection: dateProxy, displayedComponents: .date, label:{ Text("Please enter a date") }
            )
            .labelsHidden()
            .datePickerStyle(WheelDatePickerStyle())

            // Week number and day
            Text("Week \(Int(weekOfYear.rounded()))")
            Text("\(weekDay)")

            // Slider
            Slider(value: $weekOfYear, in: 1...lastWeekOfThisYear, onEditingChanged: { _ in
                    self.updateDateFromWeek()
                })
            }

    }

    func updateWeekAndDayFromDate() {
        self.weekOfYear = Self.weekOfYear(for: self.date)
        self.weekDay = Self.weekDay(for: self.date)
    }

    func updateDateFromWeek() {
        // To do
    }

    func setToday() {
        // To do
    }

    func getWeekDay(_ date: Date) -> String {
        ""
    }
}

struct TestDatePicker_Previews: PreviewProvider {
    static var previews: some View {
        TestDatePicker()
    }
}

这篇关于如何使用SwiftUI和Combine检测Datepicker的值变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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