DateFormatter를 매번 생성해서 사용하는 것은 메모리상 생각보다 더 비싼 비용입니다.
DateFormatter는 Thread-Safe 하기 때문에, 전역적으로 생성해서 재사용 (캐싱) 하는 것을 제안합니다.
[ Data Formatting Guide from Apple ]
Cache Formatters for Efficiency
Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.
날짜 포맷터를 생성하는 것은 비용이 많이 드는 작업입니다. 포맷터를 자주 사용할 가능성이 높은 경우 일반적으로 여러 인스턴스를 생성하고 폐기하는 것보다 단일 인스턴스를 캐시하는 것이 더 효율적입니다. 한 가지 접근 방식은 정적 변수를 사용하는 것입니다.
실제로 메모리 시간을 측정한 테스트 결과를 보면, 많은 경우 UIView 를 생성하는 것보다도 더 비싼 비용임을 확인할 수 있습니다.
출처: https://sarunw.com/posts/how-expensive-is-dateformatter/
DateFormatter
를 전역적으로 생성해서 재사용 할 때의 문제는 크지 않을까요?DateFormatter
인스턴스를 유지하는데 사용되는 공간복잡도는 그리 크지 않습니다.DateFormatter
는 Thread-Safe 합니다. (DateFormatter 공식문서)extension Date {
func format(to dateFormat: String) -> Date {
let dateString = string(to: dateFormat)
// 🤯 인스턴스 매번 생성
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
return dateFormatter.date(from: dateString) ?? self
}
func string(to dateFormat: String) -> String {
// 🤯 인스턴스 매번 생성
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
dateFormatter.locale = Locale(identifier: "ko_KR")
return dateFormatter.string(from: self)
}
}
enum DateFormat: String {
/// 날짜 - "yyyy.MM.dd"
case yearMonthDate = "yyyy.MM.dd"
/// 월, 일 - "MM.dd"
case monthDate = "MM.dd"
...
}
extension DateFormat {
private static var cachedFormatters: NSCache<NSString, DateFormatter> = .init()
// MARK: - Public
/// 각 DateFormat에 따른 formatter
///
/// - 미리 생성해둔 인스턴스를 재사용함
/// - DateFormatter 의 생성 비용은 굉장히 비싸서 재사용 하는 것이 효율적
/// - DateFormatter는 thread-safe 하기에 전역적으로 사용 가능
var formatter: DateFormatter {
Self.cachedFormatter(ofDateFormat: rawValue)
}
static func cachedFormatter(ofDateFormat dateFormat: String) -> DateFormatter {
let dateFormatKey = NSString(string: dateFormat)
if let cachedFormatter = cachedFormatters.object(forKey: dateFormatKey) {
return cachedFormatter
}
let formatter = makeFormatter(withDateFormat: dateFormat)
cachedFormatters.setObject(formatter, forKey: dateFormatKey)
return formatter
}
// MARK: - Private Methods
private static func makeFormatter(withDateFormat dateFormat: String) -> DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = dateFormat
formatter.locale = Locale(identifier: "ko_KR")
return formatter
}
}
/// 사용
extension Date {
func formattedString(dateFormat: DateFormat) -> String {
// ✅ 딕셔너리로 캐싱된 DateFormatter 를 재사용
return dateFormat.formatter.string(from: self)
}
}
이제 sexy하게 code를 작성할 수 있겠네욤 하핫 좋은글 감사합니다