SwiftUI MultiDatePicker初始非空选择无法取消的问题修复
MultiDatePicker初始选中日期无法取消的解决方法
在SwiftUI中使用MultiDatePicker时,通过init方法或静态初始化设置初始选中日期后,发现无法取消该初始选中项,该日期始终保留在dates集合中,测试环境为Xcode 14.0.1和14.1 beta 3。
问题代码示例
初始化方式的问题代码
import SwiftUI struct ContentView: View { @State private var dates: Set<DateComponents> init() { let now = Calendar.current.dateComponents([.year, .month, .day], from: .now) _dates = State(initialValue: [now]) } var body: some View { VStack { MultiDatePicker("", selection: $dates) .onChange(of: dates) {_ in print("Selection changed") } Text(datesStr) }.padding() } var datesStr: String { dates .map{ Calendar.current.date(from: $0)!.formatted(date: .numeric, time: .omitted) } .joined(separator: "\n") } }
静态初始化的问题代码
@State private var dates: Set<DateComponents> = [Calendar.current.dateComponents([.year, .month, .day], from: .now)]
解决方法
改用ObservableObject配合@StateObject来管理选中日期集合,替代直接使用@State:
import SwiftUI class DateSelectionViewModel: ObservableObject { @Published var dates: Set<DateComponents> = [] init() { let now = Calendar.current.dateComponents([.year, .month, .day], from: .now) dates.insert(now) } } struct ContentView: View { @StateObject private var viewModel = DateSelectionViewModel() var body: some View { VStack { MultiDatePicker("", selection: $viewModel.dates) .onChange(of: viewModel.dates) { _ in print("Selection changed: \(viewModel.dates.count) items") } Text(datesStr) }.padding() } var datesStr: String { viewModel.dates .compactMap{ Calendar.current.date(from: $0) } .map{ $0.formatted(date: .numeric, time: .omitted) } .joined(separator: "\n") } }
原理说明
@StateObject结合ObservableObject的@Published属性,能更精准地监听集合的增删变化,确保MultiDatePicker可以正确同步选中状态。- 直接使用
@State管理Set<DateComponents>时,SwiftUI内部的匹配逻辑存在bug,导致取消初始选中项时无法正确从集合中移除对应的元素,改用ViewModel的方式可以避开这一问题。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

