按年份部分显示保存在 CoreData 中的日期

Show dates saved in CoreData by year sections

我正在开发一个简单的应用程序,它应该根据特定范围添加日期。 目前它应该只将当前日期添加到 CoreData 并按年份将它们分类。

下面的代码有效,但它每年显示的频率与日期一样多。我知道这是因为 2 个 ForEach 循环。有谁知道如何只显示每个部分(年份)一次。添加 2 个日期时的代码和结果下方。

struct ScheduleView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Schedule.date, ascending: true)], animation: .default)
    private var dates: FetchedResults<Schedule>

    let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

    var body: some View {
        List {
            ForEach(dates, id: \.id) { date in
                Section(header: Text(String((Calendar.current.dateComponents([.year], from: date.date!)).year!))) {
                    ForEach(dates, id: \.id) { date in
                        HStack {
                            VStack {
                                Text("\((Calendar.current.dateComponents([.day], from: date.date!)).day!)")
                                Text("\(months[(Calendar.current.dateComponents([.month], from: date.date!)).month! - 1])")
                                    .foregroundColor(.blue)
                                    .fontWeight(.bold)
                            }
                            .padding(5)
                            Spacer()
                        }
                    }
                }
            }
        }
    }
    .navigationTitle("Schedule")
    .toolbar {
        ToolbarItem(placement: .bottomBar) {
            Button(action: { addDate() }, label: {
                Label("Add Dates", systemImage: "calendar.badge.plus")
            })
        }
    }

    private func addDate() {
        withAnimation {
            let newDate = Schedule(context: viewContext)
            newDate.id = UUID()
            newDate.date = Date()

            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

Example with 2 dates added with the add date button

你非常接近...我不得不将 Schedule 更改为 Item 因为你没有提供关于你的对象的信息,但其他一切都应该有效。

struct YearSort: View {
    @Environment(\.managedObjectContext) private var viewContext
    //Matched Fetch to generic Item since details about Entity were not provided
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)], animation: .default)
    private var dates: FetchedResults<Item>
    
    let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    var years: [Int]{
        var result = [Int]()
        for date in dates{
            let year = Calendar.current.dateComponents([.year], from: date.timestamp!).year!
            if !result.contains(year){
                result.append(year)
            }
        }
        return result
    }
    var body: some View {
        List {
            ForEach(years, id: \.self) { year in
                Section(header: Text(year.description)) {
                    ForEach(dates.filter({date in
                         Calendar.current.dateComponents([.year], from: date.timestamp!).year! == year
                    }), id: \.id) { date in
                        HStack {
                            VStack {
                                Text("\((Calendar.current.dateComponents([.day], from: date.timestamp!)).day!)")
                                Text("\(months[(Calendar.current.dateComponents([.month], from: date.timestamp!)).month! - 1])")
                                    .foregroundColor(.blue)
                                    .fontWeight(.bold)
                            }
                            .padding(5)
                            Spacer()
                        }
                    }
                }
            }
        }.navigationTitle("Schedule")
        .toolbar {
            ToolbarItem(placement: .bottomBar) {
                Button(action: { addDate() }, label: {
                    Label("Add Dates", systemImage: "calendar.badge.plus")
                })
            }
        }
    }
    
    
    private func addDate() {
        withAnimation {
            let newDate = Item(context: viewContext)
            //newDate.id = UUID()
            //Provides a random yeah +/- 3 years
            newDate.timestamp = Date().addingTimeInterval(TimeInterval(-60*60*24*366*Int.random(in: -3...3)))
            
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}