2014년 10월 31일 금요일

NSDate를 Swift스럽게 다뤄보기

기존 Objective-C에 비해 Swift가 가지는 장점 중 하나는 오퍼레이터 오버로딩(Operator Overloading) 이라고 생각한다. 이걸 잘 쓰면 코드가 짧아지면서 가독성이 좋아질 수도 있기 때문이다. (물론 반대로 가독성이 나빠질 수도 있지만...)

두 NSDate 객체의 시간이 같은지 비교하는 것을 생각해보자. ObjC의 경우 compare 라는 메소드를 활용해 비교가 가능하지만 코딩하기에는 좀 귀찮다. 그래서 미리 이걸 '==' 이라는 비교연산자로 오버로딩 해 보자.
func == (left: NSDate, right: NSDate) -> Bool {
    return left.compare(right) == NSComparisonResult.OrderedSame
}
이렇게 미리 코딩해 두면 두 NSDate 객체가 동일한지를 더 간단하게 비교 할 수 있다.
let date1: NSDate = ...
let date2: NSDate = ...

if date1 == date2 {
    ...
}
이런 식이다.

물론 이런 방법을 알게 되었으니, 이제 두 NSDate 중 어떤 녀석이 미래인지 과거인지 파악하는 것도 만들 수 있다.
func > (left: NSDate, right: NSDate) -> Bool {
    return left.compare(right) == NSComparisonResult.OrderedDescending
}
사실 이 꺽쇠 비교 연산자는 잘못 사용하면 가독성을 떨어뜨릴 지도 모른다. 하지만 개인적으론 날짜나 시간을 비교하기엔 괜찮은 비교 연산자라고 생각한다.
if date1 > date2 {
    // date1이 date2보다 더 미래이다. (date1 is future than date2)
} else {
    ...
}
만약 이런 식으로 쓴다면 동일한 방식으로 '>=' 이나 '<', '<=' 같은 연산자도 오버로딩해서 쓸 수 있을 것이다. (코드는 생략한다. 아주 쉬우니...)

마지막으로 한가지 더, 두 NSDate의 차이, 즉 한 NSDate에서 다른 NDate 객체 사이에 얼마의 시간 차이가 있을지를 오퍼레이터 오버로딩으로 구현해 보자. 여기서 시간 차이는 초 단위로 계산한다.
func - (left: NSDate, right: NSDate) -> NSTimeInterval {
    return left.timeIntervalSinceDate(right)
}
이제 NSDate 객체 끼리에 빼기 연산자를 사용하면 두 시간의 차이를 NSTimeInterval 이라는 타입의 초 단위 데이터로 얻어 올 수 있다.
let interval = date1 - date2
println("\(date1) + \(interval) seconds = \(date2)")
초 단위로 차이를 알게 되었으니 이를 60으로 나누면 분 단위가 나올거고 이런 식으로 원하는 단위로 가공하는데는 문제가 없을 것이다.

개인적으로 이런 오퍼레이터 오버로딩이 마음에 들어서 개인 라이브러리화 해서 만들어 두었다. 만약 전체소스를 구경하고 싶다면 아래 URL을 방문해 보면 된다.

https://github.com/seorenn/SRChoco/blob/master/SRChoco/Utilities/NSDateExtensions.swift

댓글 없음 :