0

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

我把这篇文章作为一个起点......但我的代码,目前,在nil和之间切换几次后就崩溃了Date()

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

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()
        }
    }
}

提前致谢!

4

1 回答 1

0

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

通过阅读Jim Dovey的这篇博客,我几乎了解了所有关于 SwiftUI 绑定(使用核心数据)的知识。剩下的就是一些研究和几个小时犯错的结合。

因此,当我使用 Jim 的技术Extensions在 SwiftUI 上进行创建时,Binding我们最终会得到类似这样的结果,以取消对 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-12-01T12:49:25.010 回答