You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:15:37