일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- environmentobjet
- iphone
- realitykit
- 달력
- Performance
- swift
- 데이터최적화
- CS
- Network
- arkit
- combine
- stateobject
- Animation
- UIKit
- ios
- SwiftUI
- RxSwift
- gesture
- authentication
- withAnimation
- state
- 네트워크
- auth
- ar
- dataflow
- Concurrency
- WWDC
- firebase
- fullscreencover
- GCD
- Today
- Total
XLOG
[SwiftUI] 날짜 계산, 월간달력 만들기 본문
이전 Posting 에 달력에 활용할 무한스크롤에 대한 아이디어를 적어서 포스팅 한 적이 있다.
그래서 이번엔 그 스크롤에 활용할 달력을 만들어 보려고 한다.
그러기 위해선 Swift 에서 날짜를 다루는 것들에 대해 먼저 알아봐야 한다.
그래서 Date, Calendar 를 확인할 예정이다.
우선 Date
기본 파라미터 없이 init을 하게 되면 현재 날짜와 시간을 알려준다. 여기서 timeInterval 은 시간차(초 단위) 날짜를 구한다고 알고 있으면 된다.
Calendar 는 달력유닛과 특정 시점으로 정의를 내려준다고 한다. 그리고 날짜 계산 및 비교도 제공을 해준다.
여기서 달력 유닛은 말그대로 달력의 종류인데 일반적으로 양력(그레고리언) 을 사용한다.
이것과 관련된 설정으로 아이폰에서 일반 > 언어 및 지역 > 캘린더 에 가면 선택할 수 있는 옵션이 보이는 것으로 생각하면 된다.
사실 Calendar 에 timezone, locale 이 나누어져 있어서 맨 처음 왜 따로 계산하는지 궁금했었다. 하지만 이유는 간단했다. 아무리 Locale 이 같더라도 미국처럼 땅이 크면 도시마다 시차가 발생한다. 그럴때 timezone을 구분해서 사용하게 된다.
// "Mar 4, 2023 at 12:42 PM"
let currentDate = Date()
// Calendar 를 사용할 경우 뒤에 current 혹은 identifier를 줘야한다.
// 앞서 설명한 것과 마찬가지로 어떠한 달력 계산 방식을 사용하는지를 설정해줘야 하기 때문이다.
let calendar = Calendar.current
// "Mar 1, 2023 at 12:00 AM"
let startDate = calendar.date(from: Calendar.current.dateComponents([.year, .month], from: currentDate))!
//{lowerBound 1, upperBound 32}
let range = calendar.range(of: .day, in: .month, for: startDate)!
// 한달치의 달력 컴퍼넌트를 가지고 온다.
let rangeMonth = range.compactMap{ day -> Date in
return calendar.date(byAdding: .day, value: day - 1, to: startDate)!
}
가장 기본적인 코드들이다. 위의 함수들을 사용하면 나는 해당날짜의 한달치의 날짜 배열을 확인할 수 있다.
하지만 문제는 한달의 시작은 일요일 혹은 월요일 부터 시작하지 않는다는 것이다.
그것을 위해 startDate 를 구해준 것이다.
let calendar = Calendar.current
// "Mar 1, 2023 at 12:00 AM"
let startDate = calendar.date(from: Calendar.current.dateComponents([.year, .month], from: currentDate))!
// 일요일1 ~ 토요일 7
// 4
let startIndex = calendar.component(.weekday, from: startDate)
//weekday: 7 isLeapMonth: false
let firstday = calendar.dateComponents([.weekday], from: startDate)
// 4
firstday.weekday
이렇게 원하는 날짜(그 달의 시작 날짜)가 무슨 요일인지 확인을 해준다.
let days = ["일", "월", "화", "수", "목", "금", "토"]
VStack {
// 맨 위 날짜 표시
HStack(spacing: 0) {
ForEach(days, id: \.self) { day in
Text(day)
.foregroundColor(day == "sun" ? .red : .black)
.frame(maxWidth: .infinity)
}
}
// 칼럼을 이용하여 7개의 칼럼을 가지는 LazyVGrid를 사용
let columns = Array(repeating: GridItem(.flexible()), count: 7)
LazyVGrid(columns: columns, spacing: 15) {
// 첫째날이 일요일이 아닌경우 빈 칸을 추가해준다
let firstDay = Calendar.component(.weekday, from: startDate)
if firstDay > 1 {
ForEach(1 ..< firstDay) { i in
Text("")
}
}
// 시작 날짜의 요일
// 그 이후부터 추가
ForEach(vm.currnetMonthlyDates) { value in
if value.day > 0 {
Text("\(value.day)")
}
}
}
}
'Swift > SwiftUI' 카테고리의 다른 글
[SwiftUI] Animation 적용 기본 이론편 (0) | 2023.08.07 |
---|---|
[SwiftUI] QR Code Scanner 만들기 (SwifUI 에 ViewController 사용하기) (1) | 2023.03.08 |
[SwiftUI] 캘린더용 InfinityScroll 로직에 대한 아이디어 (0) | 2023.02.27 |
[SwiftUI] onAppear 에서 async 함수 실행하기 (0) | 2023.02.18 |
[SwiftUI] Scroll Value 구하기 (0) | 2023.01.30 |