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

SwiftUI动态日期Button列表单选及选中日期存储问题求助

解决方案

1. 重构Day视图,用外部绑定控制选中状态

移除Day内部独立的选中状态,改用@Binding接收外部的选中状态,点击时直接通知父组件更新选中日期:

struct Day: View {
    let date: Date
    @Binding var isSelected: Bool
    
    private var dateString: String {
        date.formatted(Date.FormatStyle().day(.twoDigits).month(.twoDigits))
    }
    
    var body: some View {
        Button(dateString) {
            isSelected.toggle()
        }
        .buttonStyle(.borderedProminent)
        .tint(isSelected ? .blue : .gray)
    }
}

2. 修改DaysPanel,统一管理日期列表与选中状态

不再存储Day视图数组,改用日期数组作为数据源(视图不能直接作为ForEach的可识别元素),同时通过@Binding接收外部的选中日期,每个Day的选中状态通过对比自身日期与全局选中日期确定:

// 确保常量全局可访问
let SECONDS_IN_DAY: TimeInterval = 86400
let DAYS_IN_WEEK = 7

struct DaysPanel: View {
    @Binding var selectedDate: Date?
    private var currentDate: Date
    private var dateList: [Date] = []
    
    init(nbWeeks: Int, selectedDate: Binding<Date?>) {
        self._selectedDate = selectedDate
        self.currentDate = User.shared.startDate
        for _ in 1...nbWeeks {
            addOneWeek()
        }
    }
    
    mutating private func addOneDay() {
        dateList.append(currentDate)
        currentDate = currentDate.addingTimeInterval(SECONDS_IN_DAY)
    }
    
    mutating private func addOneWeek() {
        for _ in 1...DAYS_IN_WEEK {
            addOneDay()
        }
    }
    
    var body: some View {
        ScrollView(.horizontal) {
            HStack(spacing: 8) {
                ForEach(dateList, id: \.self) { date in
                    Day(
                        date: date,
                        isSelected: .constant(selectedDate == date)
                    )
                    .onTapGesture {
                        // 单选逻辑:点击已选中的日期则取消,否则选中当前日期
                        selectedDate = selectedDate == date ? nil : date
                    }
                }
            }
            .padding()
        }
    }
}

3. 在HomeView中管理选中日期并获取结果

在HomeView中定义全局选中状态,通过Binding传递给DaysPanel,直接获取选中的日期:

struct HomeView: View {
    @State private var selectedDate: Date?
    
    var body: some View {
        VStack {
            DaysPanel(nbWeeks: 2, selectedDate: $selectedDate)
            
            // 展示选中结果(可选)
            if let date = selectedDate {
                Text("选中的日期:\(date.formatted(.dateTime.day().month()))")
                    .padding()
            } else {
                Text("未选中任何日期")
                    .padding()
            }
        }
    }
}

核心逻辑说明

  • 状态提升:将选中状态从Day组件转移到HomeView,通过Binding在组件间共享状态,确保同一时间仅能选中一个日期。
  • 数据源优化:用日期数组替代视图数组,符合SwiftUI对ForEach数据源的要求,同时简化数据管理逻辑。
  • 单选控制:通过对比当前日期与全局选中日期,点击时切换选中状态,实现单选效果。

内容的提问来源于stack exchange,提问作者user21299219

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:13:29