SwiftUI DatePicker Binding optional Date, valid nil
SwiftUI DatePicker Binding optional Date, valid nil
我正在试验来自 https://alanquatermain.me/programming/swiftui/2019-11-15-CoreData-and-bindings/
的代码
我的目标是让 DatePicker 绑定到 Binding< Date? > 允许 nil 值而不是初始化 Date();这很有用,如果你的核心数据模型实体中有 Date 属性,它接受 nil 作为有效值。
这是我的 swift 游乐场代码:
extension Binding {
init<T>(isNotNil source: Binding<T?>, defaultValue: T) where Value == Bool {
self.init(get: { source.wrappedValue != nil },
set: { source.wrappedValue = [=10=] ? 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 = [=11=] ? 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 时出现问题(参考绑定扩展)
问题是 DatePicker
抓取绑定并且即使您将其从视图中移除也不会很快释放它,由于 Toggle
操作,因此它会在可选的强制解包时崩溃,变成零...
这个崩溃的解决方案是
DatePicker(
"Due Date",
selection: Binding<Date>(get: {self.testDate ?? Date()}, set: {self.testDate = [=10=]}),
displayedComponents: .date
)
我在所有 SwiftUI 选择器中使用的替代解决方案...
通过阅读 that blog by Jim 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 = [=10=] == source.wrappedValue ? value : [=10=] }
)
}
}
然后可以像这样在整个代码中使用...
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)
... 根据 UISegmentedControl
和 selectedSegmentIndex
.
的文档,将分段样式选择器的 index
设置为 -1
The default value is noSegment (no segment selected) until the user
touches a segment. Set this property to -1 to turn off the current
selection.
我正在试验来自 https://alanquatermain.me/programming/swiftui/2019-11-15-CoreData-and-bindings/
的代码我的目标是让 DatePicker 绑定到 Binding< Date? > 允许 nil 值而不是初始化 Date();这很有用,如果你的核心数据模型实体中有 Date 属性,它接受 nil 作为有效值。
这是我的 swift 游乐场代码:
extension Binding {
init<T>(isNotNil source: Binding<T?>, defaultValue: T) where Value == Bool {
self.init(get: { source.wrappedValue != nil },
set: { source.wrappedValue = [=10=] ? 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 = [=11=] ? 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 时出现问题(参考绑定扩展)
问题是 DatePicker
抓取绑定并且即使您将其从视图中移除也不会很快释放它,由于 Toggle
操作,因此它会在可选的强制解包时崩溃,变成零...
这个崩溃的解决方案是
DatePicker(
"Due Date",
selection: Binding<Date>(get: {self.testDate ?? Date()}, set: {self.testDate = [=10=]}),
displayedComponents: .date
)
我在所有 SwiftUI 选择器中使用的替代解决方案...
通过阅读 that blog by Jim 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 = [=10=] == source.wrappedValue ? value : [=10=] }
)
}
}
然后可以像这样在整个代码中使用...
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)
... 根据 UISegmentedControl
和 selectedSegmentIndex
.
index
设置为 -1
The default value is noSegment (no segment selected) until the user touches a segment. Set this property to -1 to turn off the current selection.