SwiftUI DatePicker 绑定可选日期,有效 nil

wk.*_*tal 10 core-data ios swift swift-playground swiftui

我正在试验来自https://alanquatermain.me/programming/swiftui/2019-11-15-CoreData-and-bindings/ 的代码

我的目标是让 DatePicker 绑定到 Binding< Date? > 允许 nil 值而不是初始化 Date(); 这很有用,如果您的核心数据模型实体中有 Date 属性接受 nil 作为有效值。

这是我的快速游乐场代码:

extension Binding {
    init<T>(isNotNil source: Binding<T?>, defaultValue: T) where Value == Bool {
        self.init(get: { source.wrappedValue != nil },
                  set: { source.wrappedValue = $0 ? defaultValue : nil})
    }
}

struct LiveView: View {
    @State private var testDate: Date? = nil
    var body: some View {
        VStack {
            Text("abc")

            Toggle("Has Due Date",
                   isOn: Binding(isNotNil: $testDate, defaultValue: Date()))

            if testDate != nil {
                DatePicker(
                    "Due Date",
                    selection: Binding($testDate)!,
                    displayedComponents: .date
                )
            }
        }
    }
}

let liveView = LiveView()
PlaygroundPage.current.liveView = UIHostingController(rootView: liveView)
Run Code Online (Sandbox Code Playgroud)

我找不到修复此代码的解决方案。它在切换开关第一次打开时起作用,但在切换开关关闭时崩溃。

当我删除 DatePicker 并将代码更改为以下代码时,代码似乎运行正常:

extension Binding {
    init<T>(isNotNil source: Binding<T?>, defaultValue: T) where Value == Bool {
        self.init(get: { source.wrappedValue != nil },
                  set: { source.wrappedValue = $0 ? defaultValue : nil})
    }
}

struct LiveView: View {
    @State private var testDate: Date? = nil
    var body: some View {
        VStack {
            Text("abc")

            Toggle("Has Due Date",
                   isOn: Binding(isNotNil: $testDate, defaultValue: Date()))

            if testDate != nil {
                Text("\(testDate!)")
            }
        }
    }
}

let liveView = LiveView()
PlaygroundPage.current.liveView = UIHostingController(rootView: liveView)
Run Code Online (Sandbox Code Playgroud)

我怀疑这与这部分代码有关

DatePicker("Due Date", selection: Binding($testDate)!, displayedComponents: .date )
Run Code Online (Sandbox Code Playgroud)

或者

source.wrappedValue 设置回 nil 时的问题(参考绑定扩展)

Asp*_*eri 8

问题是DatePicker抓取绑定并且即使您将其从视图中移除也不会很快释放它,因为Toggle动作,因此它在强制解包可选时崩溃,这变为 nil ...

此崩溃的解决方案是

DatePicker(
    "Due Date",
    selection: Binding<Date>(get: {self.testDate ?? Date()}, set: {self.testDate = $0}),
    displayedComponents: .date
)
Run Code Online (Sandbox Code Playgroud)