SwiftUI:如何获取今天的日历视图?

Hus*_*iry 5 swiftui ios14

我一直在 SwiftUI 中寻找一种方法,仅以小时间隔获取今天的视图,就像 iOS 的日历应用程序一样,如果 SwiftUI 有默认的内置视图,那么那就太好了,如果没有,并且有一个 GitHub 库可以完成这项工作那么我也可以使用它,我在网上找到了一种在 SwiftUI 中显示年/月视图的方法:

import SwiftUI

fileprivate extension DateFormatter {
    static var month: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM"
        return formatter
    }

    static var monthAndYear: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM yyyy"
        return formatter
    }
}

fileprivate extension Calendar {
    func generateDates(
        inside interval: DateInterval,
        matching components: DateComponents
    ) -> [Date] {
        var dates: [Date] = []
        dates.append(interval.start)

        enumerateDates(
            startingAfter: interval.start,
            matching: components,
            matchingPolicy: .nextTime
        ) { date, _, stop in
            if let date = date {
                if date < interval.end {
                    dates.append(date)
                } else {
                    stop = true
                }
            }
        }

        return dates
    }
}

struct WeekView<DateView>: View where DateView: View {
    @Environment(\.calendar) var calendar

    let week: Date
    let content: (Date) -> DateView

    init(week: Date, @ViewBuilder content: @escaping (Date) -> DateView) {
        self.week = week
        self.content = content
    }

    private var days: [Date] {
        guard
            let weekInterval = calendar.dateInterval(of: .weekOfYear, for: week)
            else { return [] }
        return calendar.generateDates(
            inside: weekInterval,
            matching: DateComponents(hour: 0, minute: 0, second: 0)
        )
    }

    var body: some View {
        HStack {
            ForEach(days, id: \.self) { date in
                HStack {
                    if self.calendar.isDate(self.week, equalTo: date, toGranularity: .month) {
                        self.content(date)
                    } else {
                        self.content(date).hidden()
                    }
                }
            }
        }
    }
}

struct MonthView<DateView>: View where DateView: View {
    @Environment(\.calendar) var calendar

    let month: Date
    let showHeader: Bool
    let content: (Date) -> DateView

    init(
        month: Date,
        showHeader: Bool = true,
        @ViewBuilder content: @escaping (Date) -> DateView
    ) {
        self.month = month
        self.content = content
        self.showHeader = showHeader
    }

    private var weeks: [Date] {
        guard
            let monthInterval = calendar.dateInterval(of: .month, for: month)
            else { return [] }
        return calendar.generateDates(
            inside: monthInterval,
            matching: DateComponents(hour: 0, minute: 0, second: 0, weekday: calendar.firstWeekday)
        )
    }

    private var header: some View {
        let component = calendar.component(.month, from: month)
        let formatter = component == 1 ? DateFormatter.monthAndYear : .month
        return Text(formatter.string(from: month))
            .font(.title)
            .padding()
    }

    var body: some View {
        VStack {
            if showHeader {
                header
            }

            ForEach(weeks, id: \.self) { week in
                WeekView(week: week, content: self.content)
            }
        }
    }
}

struct CalendarView<DateView>: View where DateView: View {
    @Environment(\.calendar) var calendar

    let interval: DateInterval
    let content: (Date) -> DateView

    init(interval: DateInterval, @ViewBuilder content: @escaping (Date) -> DateView) {
        self.interval = interval
        self.content = content
    }

    private var months: [Date] {
        calendar.generateDates(
            inside: interval,
            matching: DateComponents(day: 1, hour: 0, minute: 0, second: 0)
        )
    }

    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                ForEach(months, id: \.self) { month in
                    MonthView(month: month, content: self.content)
                }
            }
        }
    }
}

struct RootView: View {
    @Environment(\.calendar) var calendar

    private var year: DateInterval {
        calendar.dateInterval(of: .year, for: Date())!
    }

    var body: some View {
        CalendarView(interval: year) { date in
            Text("30")
                .hidden()
                .padding(8)
                .background(Color.blue)
                .clipShape(Circle())
                .padding(.vertical, 4)
                .overlay(
                    Text(String(self.calendar.component(.day, from: date)))
                )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图只获得像这样的今天的视图(顶部没有该月的日期):

iOS 日历应用程序

更新:

到目前为止,我在重新创建时间线视图方面取得了进展。

import SwiftUI

struct TimelineView: View {
    let hours: [String] = ["12 AM","1 AM", "2 AM", "3 AM", "4 AM", "5 AM", "6 AM", "7 AM", "8 AM", "9 AM", "10 AM", "11 AM", "12 PM", "1 PM", "2 PM", "3 PM", "5 PM", "6 PM", "7 PM", "8 PM", "9 PM", "10 PM", "11 PM"]
    var body: some View {
        ScrollView {
            HStack {
                VStack(spacing: 24) {
                    ForEach(hours, id: \.self) { hour in
                        HStack {
                            Text(hour)
                                .font(Font.custom("Avenir", size: 9))
                                .frame(width: 28, height: 20, alignment: .center)
                            VStack {
                                Divider()
                            }
                        }
                    }
                }
                Spacer()
            }
        }
        .padding(.top, 150)
        .padding(.bottom, 32)
        .padding(.horizontal, 16)
        .background(backgroundPrimary)
        .ignoresSafeArea()
    }
}
Run Code Online (Sandbox Code Playgroud)

时间线视图

我需要帮助重新构造我制作字符串的时间数组,因为我很确定这不是正确的方式,另外我想将其设为日期类型,因为我有带有时间戳的事件并且需要比较数组我有多少时间与事件的时间来查看它将填充哪个块

Uma*_*han 0

没有内置的方法可以为您提供所需的功能,但我可以给您一个提示,以便您可以使用电子表格自行创建 -> 在电子表格中填写时间线,然后添加宽度匹配的水平视图它的父级偏移量和高度为 2 或 3,然后您可以添加 60 秒的计时器,该计时器将使用一些计算来更新该行在父级偏移量内的位置。