Calendar를 이용한 예약타이머 만들기
사내에서, 특정 시간부터 특정 시간까지 앱 스플래시 화면을 변경해야하는 작업이 생겼다.
일반적으로 앱 내에서 Calendar 객체를 이용해 만드는 방법과 서버 드리븐 방법이 있다. 앱 내에서 Calendar 객체를 이용한 경우에는 유저가 디바이스의 시스템 시간 셋팅을 건드리는 경우에 원하는대로 동작하지 않을 수 있다. 그럼에도 불구하고 Calendar로 예약 타이머로 작업하게 되어서 해당 방법을 소개하고자 한다.
주요 포인트는
- 예약시간을 앱 내에서 관리해야하는 시점에 사방에서 호출하지 않도록 Enum 타입 하나로 관리한다.
- Manager 객체가 init되는 시점에 from 값 (현재시간), to 값(언제까지 수행되야 하는지에 대한 시간값) 을 받는다.
- 받은 값을 필요한 시점에 메서드 호출하여 ComparisonResult 타입으로 반환한다.
ReserveDateEnumType
- case 단위로 관리, case self에 대한 Date타입을 정의한다.
public enum ReserveDateType {
case splashEvent
public var reserveDate: Date? {
switch self {
case .splashEvent:
return Calendar.current.date(
from: DateComponents(
year: 2023,
month: 10,
day: 28,
hour: 23,
minute: 59
))
}
}
}ReserveTimeManager
- init 시점에 toDate는 만들어둔 EnumType으로만 동작하도록 제한한다.
- 필요한 시점에 compare함수를 호출하여 해당 결과값을 반환
struct ReserveTimeManager {
private let fromDate: Date
private let toDate: Date?
private let granularity: Calendar.Component
init(fromDate: Date, toDate: ReserveDateType, granularity: Calendar.Component? = nil) {
self.fromDate = fromDate
self.toDate = toDate.reserveDate
self.granularity = granularity ?? .minute
}
func compare() -> ComparisonResult? {
guard let toDate = self.toDate else { return nil }
return Calendar.current.compare(fromDate, to: toDate, toGranularity: granularity)
}
}ComparisonResult란
- orderedAscending : 왼쪽 피연산자가 오른쪽 피연산자보다 작다.
- orderedSame: 왼쪽 피연산자가 오른쪽 피연산자와 동일하다.
- orderedDescending: 왼쪽 피연산자가 오른쪽 피연산자보다 크다.
/*
These constants are used to indicate how items in a request are ordered, from the first one given in a method invocation or function call to the last (that is, left to right in code).
Given the function:
NSComparisonResult f(int a, int b)
If:
a < b then return NSOrderedAscending. The left operand is smaller than the right operand.
a > b then return NSOrderedDescending. The left operand is greater than the right operand.
a == b then return NSOrderedSame. The operands are equal.
*/
@frozen public enum ComparisonResult : Int, @unchecked Sendable {
case orderedAscending = -1
case orderedSame = 0
case orderedDescending = 1
}
Date타입을 비교하고 아래와 같이 사용할 수 있다.
let result = CalendarManager(
fromDate: date,
toDate: .splashEvent,
granularity: .month
).compare()
switch result {
case .orderedSame:
return true
default:
return false
}