在使用SwiftUI和Combine时如何检测Datepicker的值变化? 每当日期选择轮移动时,我都需要调用一个方法,以更新文本和滑块。
我一直在寻找确定值变化的特定方法(使用UIKit可以将操作与事件相关联),但是显然我在文档中没有找到任何有用的方法(我尝试过onTapGesture方法,但这不是我想要的,因为它会迫使用户点击选择器来更新其他视图,而我希望每当用户移动方向盘时就进行自动更新。
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
}
}
我想可以使用Combine(可以观察的对象,已发布,接收器等)解决此问题,但是我还没有使用Combine的经验,因此我想寻求帮助...有什么想法吗? :)
非常感谢!
答案 0 :(得分:3)
请在下面找到一种可能的方法(对您的代码进行了一些修改)。这是使源状态透明以激活其中的依赖关系的想法。希望它会有所帮助。
这是演示
这是代码
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()
}
}
答案 1 :(得分:0)
使用ObservableObject的可能方法
(1,[3])
答案 2 :(得分:0)
另一种方法是,只要更改日期,就会在viewModel中调用观察者
class TestPikerModel: ObservableObject {
@Published var expireDate: Date = Date()
init() {
setupObserver()
}
private func setupObserver() {
$expireDate
.sink { date in
// do some networking call
}
.store(in: &cancellables)
}
}
struct TestPikerView: View {
@ObservedObject var testPikerModel = TestPikerModel()
@State private var weekOfYear = Double(Calendar.current.component(.weekOfYear, from: Date()) )
var body: some View {
VStack {
Text("\(Int(weekOfYear))")
DatePicker("", selection: $testPikerModel.expireDate, displayedComponents: .date)
.datePickerStyle(CompactDatePickerStyle())
.clipped()
.labelsHidden()
}
}
}