【问题标题】:SwiftUI DatePicker Binding optional Date, valid nilSwiftUI DatePicker 绑定可选日期,有效 nil
【发布时间】:2020-04-03 23:14:53
【问题描述】:

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

我的目标是让 DatePicker 绑定到 Binding 允许 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)

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

当我删除 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)

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

DatePicker("Due Date", selection: Binding($testDate)!, displayedComponents: .date )

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

【问题讨论】:

    标签: ios swift core-data swiftui swift-playground


    【解决方案1】:

    我在所有 SwiftUI 选择器中使用的替代解决方案...

    通过阅读that blogJim Dovey,我几乎了解了有关 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("Due Date", 
           selection: Binding($testDate, deselectTo: nil),
           displayedComponents: .date
    ) 
    

    或者当使用.pickerStyle(.segmented)

    Picker("Date Format Options", // for example 
           selection: Binding($selection, deselectTo: -1)) { ... }
        .pickerStyle(.segmented)
    

    ...根据UISegmentedControlselectedSegmentIndex 的文档,将分段样式选择器的index 设置为-1。

    默认值是 noSegment (不选择段),直到用户 触及一个片段。将此属性设置为 -1 以关闭当前 选择。

    【讨论】:

      【解决方案2】:

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

      这次崩溃的解决办法是

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

      【讨论】:

      • 您的解决方案修复了崩溃,但未按预期运行,因为我们希望 DatePicker 修改 testDate 的值。在您的代码中,DatePicker 选择在切换时绑定到 .constant(Date()) 而不是 testDate。但是,我认为您是对的,由于强制 unwrap nil optional 导致的崩溃似乎是当切换关闭时 DatePicker 仍在尝试 unwrap optional(现在设置为 nil),我希望代码不会这样做,因为我已经放了检查 testdate != nil 是否不正确。仍在寻找解决此问题的解决方案。
      • 更新了另一个不可崩溃的变体
      猜你喜欢
      • 1970-01-01
      • 2020-03-21
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多