SwiftUI 如何获取月份每一天对应的星期名称并完成展示?
实现方案
修改步骤
1. 扩展DateProvider功能
新增两个工具方法:一个用于获取指定日期对应的星期名称,另一个用于获取指定月份第一天的偏移量,保证日历排版对齐。
修改后的完整DateProvider代码如下:
class DateProvider: ObservableObject { @Published var months: [String] = [] @Published var dateData: DateType = DateType(day: "", date: "", year: "", month: "") private let trLocale = NSLocale(localeIdentifier: "tr_TR") as Locale init() { months = getMonths() dateData = getCurrentDate() } func getCurrentDate() -> DateType { let date = Date() var currentDate = Calendar.current currentDate.locale = trLocale let dateString = currentDate.component(.day, from: date) let monthNo = currentDate.component(.month, from: date) let month = currentDate.monthSymbols[monthNo - 1] let year = currentDate.component(.year, from: date) let weekNo = currentDate.component(.weekday, from: date) let day = currentDate.weekdaySymbols[weekNo - 1] return DateType(day: "\(day)", date: "\(dateString)", year: "\(year)", month: "\(month)") } func getMonths() -> [String] { let formatter = DateFormatter() formatter.locale = trLocale let monthComponents = formatter.shortMonthSymbols ?? [] return monthComponents } func getNumbersOfMonths(month: Int, year: Int) -> Int { let dateComponents = DateComponents(year: year, month: month) let calendar = Calendar.current let date = calendar.date(from: dateComponents)! let range = calendar.range(of: .day, in: .month, for: date)! let numDays = range.count return numDays + 1 } // 新增:获取指定日期的星期名称 func getWeekday(day: Int, month: Int, year: Int) -> String { var calendar = Calendar.current calendar.locale = trLocale let components = DateComponents(year: year, month: month, day: day) guard let date = calendar.date(from: components) else { return "" } let weekdayIndex = calendar.component(.weekday, from: date) // 如需完整星期名可替换为weekdaySymbols return calendar.shortWeekdaySymbols[weekdayIndex - 1] } // 新增:获取月份第一天的偏移量,用于填充前置空位 func getFirstDayOffset(month: Int, year: Int) -> Int { var calendar = Calendar.current calendar.locale = trLocale let components = DateComponents(year: year, month: month, day: 1) guard let date = calendar.date(from: components) else { return 0 } return calendar.component(.weekday, from: date) - 1 } }
2. 修改ContentView布局
调整LazyVGrid内的布局,先填充前置空位,再在每个日期下方新增星期名展示。修改后的完整ContentView代码如下:
struct ContentView: View { @State var data: DateType = DateType(day: "", date: "", year: "", month: "") @ObservedObject var dateProvider: DateProvider = DateProvider() // 固定展示2021年,可根据需求修改为动态变量 private let displayYear = 2021 var body: some View { ScrollView { VStack(spacing: 20) { VStack(spacing: 8) { Text(self.dateProvider.dateData.day) Text(self.dateProvider.dateData.date) Text(self.dateProvider.dateData.month) Text(self.dateProvider.dateData.year) } VStack(spacing: 30) { ForEach(dateProvider.months.indices, id: \.self) { index in let currentMonth = index + 1 Text("\(dateProvider.months[index])") .font(.title2) .fontWeight(.medium) LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 10) { // 填充月份第一天前的空位 ForEach(0 ..< dateProvider.getFirstDayOffset(month: currentMonth, year: displayYear), id: \.self) { _ in EmptyView() } // 日期+星期展示 ForEach(1 ..< dateProvider.getNumbersOfMonths(month: currentMonth, year: displayYear)) { item in VStack(spacing: 4) { Text("\(item)") .font(.headline) Text(dateProvider.getWeekday(day: item, month: currentMonth, year: displayYear)) .font(.caption) .foregroundColor(.secondary) } } } .padding(.horizontal) } } } .padding(.vertical) } } }
3. 原有Model无需修改
DateType结构体保持原有定义即可。
内容的提问来源于stack exchange,提问作者Ufuk Köşker
相关产品推荐
相关产品推荐

