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.