【问题标题】:Optional SwiftUI DatePicker with nil to Date and Date to nil toggle可选的 SwiftUI DatePicker 与 nil to Date 和 Date to nil 切换
【发布时间】:2021-09-02 14:46:26
【问题描述】:

我正在尝试构建一个可以处理可选日期的 DatePicker。

我使用this post 作为起点...但目前我的代码在nilDate() 之间切换几次后就崩溃了。

我怎样才能使这段代码安全?

import SwiftUI

extension Date {
    public var m3d2y4: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM dd, yyyy"
        return formatter.string(from: self)
    }
}

struct OptionalDatePicker: View {
    @Binding var date: Date?
    var nilText = "Never"
    var nilDate = Date()
    
    var body: some View {
        if let _ = date {
            datePicker
        } else {
            nilTextButton
        }
    }
    
    private var dateBinding: Binding<Date> {
        Binding(get: { date ?? nilDate }, set: { date = $0 })
    }
    
    private var dateString: String {
        dateBinding.wrappedValue.m3d2y4
    }

    private var nilTextButton: some View {
        Button(action: toggleDate) {
            Text(nilText)
        }
    }
    
    private var datePicker: some View {
        ZStack {
            HStack {
                Text(dateString)
                    .foregroundColor(.blue)
                Button(action: { toggleDate() }) {
                    Image(systemName: "xmark.circle")
                }
            }
            DatePicker("", selection: dateBinding, displayedComponents: [.date])
                .opacity(0.02) // minimum opacity to still allow tapping
                .labelsHidden()
        }
    }
    
    private func toggleDate() {
        if let _ = date {
            date = nil
        } else {
            date = nilDate
        }
    }
}


struct OptionalDatePicker_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
    
    struct ContentView: View {
        @State var date: Date? = nil
        
        var body: some View {
            HStack {
                Text("Ends")
                Spacer()
                OptionalDatePicker(date: $date)
            }
            .padding()
        }
    }
}

提前致谢!

【问题讨论】:

  • 你在这里做了一些奇怪的事情 - .opacity(0.02) 是一个原因。
  • 选择器位于文本标签的前面,这样我仍然可以在点击时调出日历。如果opacity 设置为0,它就不再是可点击的(不知道为什么?)...通过反复试验,我确定.opacity(0.02) 是仍然允许并捕获点击的最低值。如果DatePicker 有一个isPresented 参数,例如NavigationLink,我认为我不需要这样做。

标签: swift swiftui ios15


【解决方案1】:

注意到您在问题中链接到的 SO 帖子,我将在这里重复我的答案...

通过阅读Jim Doveythis blog,我几乎了解了有关 SwiftUI 绑定(使用核心数据)的所有知识。剩下的就是一些研究和几个小时的错误。

因此,当我使用 Jim 的技术在 SwiftUI Binding 上创建 Extensions 时,我们最终会得到类似这样的结果,以取消对 nil 的选择...

public extension Binding where Value: Equatable {
    init(_ source: Binding<Value>, deselectTo value: Value) {
        self.init(get: { source.wrappedValue },
                  set: { source.wrappedValue = $0 == source.wrappedValue ? value : $0 }
        )
    }
}

然后可以像这样在整个代码中使用...

Picker("", 
       selection: Binding($date, deselectTo: nil),
       displayedComponents: [.date]
) 

...其中日期是可选的,例如...

@State private var date: Date?

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 2013-07-23
    • 2018-04-29
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    相关资源
    最近更新 更多