简体   繁体   中英

How to make a Calendar List in swiftUI?

Hello guys I'm trying to make a Calendar List in swiftUI:

I want to App get the current date info and show it in index 0 of allDays list and based on the subscription, App Generate an N number of Day object after current date automatically. ie: 365 for 1 year subscription.

The final result is look like this right now it's a hard code.

在此处输入图像描述

Here is my code DataModel:

import SwiftUI
import Foundation
import Combine

struct Day : Identifiable {

var id = UUID()
var name : String
var date : String
var title : String
var color : Color
var month : String
var List : [Name?]

}

struct Name : Identifiable {

var id = UUID()
var name: String
var color: Color

}

class AppState : ObservableObject {

@Published var allDays : [Day] = [
    Day(name: "Sunday", date: "20", title: "", color: .pink, month: "Jun", List: [
        Name(id: UUID(), name: "John", color: .pink),
        Name(id: UUID(), name: "Rose", color: .pink),
        Name(id: UUID(), name: "Mike", color: .pink),
    ]),
    Day(name: "Monday", date: "21", title: "", color: .yellow, month: "Jun", List: [
        Name(id: UUID(), name: "Sara", color: .yellow),
        Name(id: UUID(), name: "Jack",color: .yellow),
    ]),
    Day(name: "Tuesday", date: "22", title: "", color: .blue, month: "Jun", List: [
        Name(id: UUID(), name: "Rachel",color: .blue),
    ]),
    Day(name: "Wednesday", date: "23", title: "", color: .green, month: "Jun", List: []),
    Day(name: "Thursday", date: "24", title: "", color: .orange, month: "Jun", List: []),
    Day(name: "Friday", date: "25", title: "", color: .purple, month: "Jun", List: []),
    Day(name: "Saturday", date: "26", title: "", color: .red, month: "Jun", List: []),
]

}

and View:

import SwiftUI

struct CalendarList: View {

@EnvironmentObject var appState : AppState

var body: some View {
    
        NavigationView {
            
            List {
                
                ForEach(appState.allDays.indices, id:\.self) { index in
                    NavigationLink(destination: Text(appState.allDays[index].name) ) {
                        HStack(alignment: .top) {
                            RoundedRectangle(cornerRadius: 23)
                                .frame(width: 74, height: 74)
                                .foregroundColor(Color.blue)
                                .overlay(
                                    VStack {
                                        Text(appState.allDays[index].date)
                                            .font(.system(size: 35, weight: .regular))
                                            .foregroundColor(.white)
                                        Text(appState.allDays[index].month)
                                            .foregroundColor(.white)
                                    }
                                )
                                .padding(.trailing ,4)
                            
                            VStack(alignment: .leading, spacing: 5) {
                                Text(appState.allDays[index].name)
                                    .font(.system(size: 20, weight: .semibold))
                                Text(appState.allDays[index].title)
                                    .font(.subheadline)
                                    .foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
    
                                
                            }
                        }
                        .padding(.vertical ,6)
                    }
                }
                
            }
            .navigationTitle("Calendar")
        }
        .navigationViewStyle(StackNavigationViewStyle())
            
}
}

struct CalendarList_Previews: PreviewProvider {
    static var previews: some View {
        CalendarList()
        }
}

You can generate the Day models with a couple of DateFormatter and Calendar methods:

extension Date {
    func dayOfWeek(withFormatter dateFormatter: DateFormatter) -> String? {
        dateFormatter.dateFormat = "EEEE"
        return dateFormatter.string(from: self).capitalized
    }
    
    func nameOfMonth(withFormatter dateFormatter: DateFormatter) -> String? {
        dateFormatter.dateFormat = "LLLL"
        return dateFormatter.string(from: self).capitalized
    }
}


func getDays(number: Int) -> [Day] {
    let today = Date()
    let formatter = DateFormatter()
    return (0..<number).map { index -> Day in
        let date = Calendar.current.date(byAdding: .day, value: index, to: today) ?? Date()
        return Day(name: date.dayOfWeek(withFormatter: formatter) ?? "", date: "\(Calendar.current.component(.day, from: date))", month: date.nameOfMonth(withFormatter: formatter) ?? "")
    }
}

Update, due to comments. Full example:


struct Day : Identifiable {
    
    var id = UUID()
    var name : String
    var date : String
    var title : String
    var color : Color
    var month : String
    var List : [Name?]
    
}

struct Name : Identifiable {
    var id = UUID()
    var name: String
    var color: Color
}

class AppState : ObservableObject {
    
    @Published var allDays : [Day] = []
    
    func generateDays(number: Int){
        let today = Date()
        let formatter = DateFormatter()
        self.allDays = (0..<number).map { index -> Day in
            let date = Calendar.current.date(byAdding: .day, value: index, to: today) ?? Date()
            return Day(name: date.dayOfWeek(withFormatter: formatter) ?? "", date: "\(Calendar.current.component(.day, from: date))", title: "", color: .red, month: date.nameOfMonth(withFormatter: formatter) ?? "", List: [])
        }
    }
}

extension Date {
    func dayOfWeek(withFormatter dateFormatter: DateFormatter) -> String? {
        dateFormatter.dateFormat = "EEEE"
        return dateFormatter.string(from: self).capitalized
    }
    
    func nameOfMonth(withFormatter dateFormatter: DateFormatter) -> String? {
        dateFormatter.dateFormat = "LLLL"
        return dateFormatter.string(from: self).capitalized
    }
}


struct CalendarList: View {
    
    @EnvironmentObject var appState : AppState
    
    var body: some View {
        
        NavigationView {
            List {
                
                ForEach(appState.allDays.indices, id:\.self) { index in
                    NavigationLink(destination: Text(appState.allDays[index].name) ) {
                        HStack(alignment: .top) {
                            RoundedRectangle(cornerRadius: 23)
                                .frame(width: 74, height: 74)
                                .foregroundColor(Color.blue)
                                .overlay(
                                    VStack {
                                        Text(appState.allDays[index].date)
                                            .font(.system(size: 35, weight: .regular))
                                            .foregroundColor(.white)
                                        Text(appState.allDays[index].month)
                                            .foregroundColor(.white)
                                    }
                                )
                                .padding(.trailing ,4)
                            
                            VStack(alignment: .leading, spacing: 5) {
                                Text(appState.allDays[index].name)
                                    .font(.system(size: 20, weight: .semibold))
                                Text(appState.allDays[index].title)
                                    .font(.subheadline)
                                    .foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
                                
                                
                            }
                        }
                        .padding(.vertical ,6)
                    }
                }
                
            }
            .navigationTitle("Calendar")
            .onAppear {
                appState.generateDays(number: 365)
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        
    }
}

This is unrelated to your issue, but I'd also personally choose to use ForEach with direct access to the Day without going through the indices :

ForEach(appState.allDays, id:\.id) { day in
    NavigationLink(destination: Text(day.name) ) {
        HStack(alignment: .top) {
            RoundedRectangle(cornerRadius: 23)
                .frame(width: 74, height: 74)
                .foregroundColor(Color.blue)
                .overlay(
                    VStack {
                        Text(day.date)
                            .font(.system(size: 35, weight: .regular))
                            .foregroundColor(.white)
                        Text(day.month)
                            .foregroundColor(.white)
                    }
                )
                .padding(.trailing ,4)
            
            VStack(alignment: .leading, spacing: 5) {
                Text(day.name)
                    .font(.system(size: 20, weight: .semibold))
                Text(day.title)
                    .font(.subheadline)
                    .foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
                
                
            }
        }
        .padding(.vertical ,6)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM