SwiftUI:如何创建自定义 UIDatePicker?
SwiftUI: how to create custom UIDatePicker?
我成功地在 SwifUI 中创建了 UIDatePicker,但是当我在选择器中更改日期轮时,日期值没有更新,这是我的代码:
struct DatePicker: UIViewRepresentable {
@Binding var date: Date
func makeUIView(context: Context) -> UIDatePicker {
let view = UIDatePicker()
view.datePickerMode = .date
return view
}
func updateUIView(_ uiView: UIDatePicker, context: Context) {
uiView.date = date
}
}
然后我从视图中这样调用它:
struct SwiftUIView: View {
@State var date = Date()
var body: some View {
DatePicker(date: self.$date)
}
}
这是可能的方法。使用 Xcode 11.2 / iOS 13.2
测试
struct DatePicker: UIViewRepresentable {
@Binding var date: Date
func makeUIView(context: Context) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.changed(_:)), for: .valueChanged)
return datePicker
}
func updateUIView(_ datePicker: UIDatePicker, context: Context) {
datePicker.date = date
}
func makeCoordinator() -> DatePicker.Coordinator {
Coordinator(date: $date)
}
class Coordinator: NSObject {
private let date: Binding<Date>
init(date: Binding<Date>) {
self.date = date
}
@objc func changed(_ sender: UIDatePicker) {
self.date.wrappedValue = sender.date
}
}
}
带有可选参数的扩展 DatePicker 方法(基于@Asperi 回答)。
struct DatePickerUIKit: UIViewRepresentable {
@Binding private var selection: Date
private let range: ClosedRange<Date>?
private var minimumDate: Date? {
range?.lowerBound
}
private var maximumDate: Date? {
range?.upperBound
}
private var minuteInterval: Int
private let datePicker = UIDatePicker()
init(selection: Binding<Date>, in range: ClosedRange<Date>?, minuteInterval: Int = 1) {
self._selection = selection
self.range = range
self.minuteInterval = minuteInterval
}
func makeUIView(context: Context) -> UIDatePicker {
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = minuteInterval
datePicker.minimumDate = minimumDate
datePicker.maximumDate = maximumDate
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.changed(_:)), for: .valueChanged)
return datePicker
}
func updateUIView(_ uiView: UIDatePicker, context: Context) {
datePicker.date = selection
}
func makeCoordinator() -> DatePickerUIKit.Coordinator {
Coordinator(selection: $selection, in: range, minuteInterval: minuteInterval)
}
class Coordinator: NSObject {
private let selection: Binding<Date>
private let range: ClosedRange<Date>?
private let minuteInterval: Int
init(selection: Binding<Date>, in range: ClosedRange<Date>? = nil, minuteInterval: Int = 1) {
self.selection = selection
self.range = range
self.minuteInterval = minuteInterval
}
@objc func changed(_ sender: UIDatePicker) {
self.selection.wrappedValue = sender.date
}
}
}
例如设置分钟间隔,SwiftUI尚不支持:
@State var dateFrom = Date()
let minMaxRange = Date().dateAtStartOf(.day)...Date().dateAtEndOf(.day) + 3.days
DatePickerUIKit(selection: $dateFrom,
range: minMaxRange, minuteInterval: 30)
我成功地在 SwifUI 中创建了 UIDatePicker,但是当我在选择器中更改日期轮时,日期值没有更新,这是我的代码:
struct DatePicker: UIViewRepresentable {
@Binding var date: Date
func makeUIView(context: Context) -> UIDatePicker {
let view = UIDatePicker()
view.datePickerMode = .date
return view
}
func updateUIView(_ uiView: UIDatePicker, context: Context) {
uiView.date = date
}
}
然后我从视图中这样调用它:
struct SwiftUIView: View {
@State var date = Date()
var body: some View {
DatePicker(date: self.$date)
}
}
这是可能的方法。使用 Xcode 11.2 / iOS 13.2
测试struct DatePicker: UIViewRepresentable {
@Binding var date: Date
func makeUIView(context: Context) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.changed(_:)), for: .valueChanged)
return datePicker
}
func updateUIView(_ datePicker: UIDatePicker, context: Context) {
datePicker.date = date
}
func makeCoordinator() -> DatePicker.Coordinator {
Coordinator(date: $date)
}
class Coordinator: NSObject {
private let date: Binding<Date>
init(date: Binding<Date>) {
self.date = date
}
@objc func changed(_ sender: UIDatePicker) {
self.date.wrappedValue = sender.date
}
}
}
带有可选参数的扩展 DatePicker 方法(基于@Asperi 回答)。
struct DatePickerUIKit: UIViewRepresentable {
@Binding private var selection: Date
private let range: ClosedRange<Date>?
private var minimumDate: Date? {
range?.lowerBound
}
private var maximumDate: Date? {
range?.upperBound
}
private var minuteInterval: Int
private let datePicker = UIDatePicker()
init(selection: Binding<Date>, in range: ClosedRange<Date>?, minuteInterval: Int = 1) {
self._selection = selection
self.range = range
self.minuteInterval = minuteInterval
}
func makeUIView(context: Context) -> UIDatePicker {
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = minuteInterval
datePicker.minimumDate = minimumDate
datePicker.maximumDate = maximumDate
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.changed(_:)), for: .valueChanged)
return datePicker
}
func updateUIView(_ uiView: UIDatePicker, context: Context) {
datePicker.date = selection
}
func makeCoordinator() -> DatePickerUIKit.Coordinator {
Coordinator(selection: $selection, in: range, minuteInterval: minuteInterval)
}
class Coordinator: NSObject {
private let selection: Binding<Date>
private let range: ClosedRange<Date>?
private let minuteInterval: Int
init(selection: Binding<Date>, in range: ClosedRange<Date>? = nil, minuteInterval: Int = 1) {
self.selection = selection
self.range = range
self.minuteInterval = minuteInterval
}
@objc func changed(_ sender: UIDatePicker) {
self.selection.wrappedValue = sender.date
}
}
}
例如设置分钟间隔,SwiftUI尚不支持:
@State var dateFrom = Date()
let minMaxRange = Date().dateAtStartOf(.day)...Date().dateAtEndOf(.day) + 3.days
DatePickerUIKit(selection: $dateFrom,
range: minMaxRange, minuteInterval: 30)