2014년 6월 23일 월요일

예제로 보는 스위프트(Swift) - MyDatetime 클래스

스위프트(Swift) 가이드 글을 올리고 나니 ‘안그래도 형편없는 글들인데 나눠져 있어서 찾아 보기도 힘들겠구나’ 라는 생각만 잔뜩 들었다. 그래서 차라리 동작 가능한 풀소스 예제를 올려보는게 더 낫겠다는 생각이 들어서 새롭게 글을 써 본다. 이번 예제는 심심해서 만들어 본 MyDatetime 클래스이다.

MyDatetime 클래스는 NSDate 에서 시간이나 날짜 등 세부 내용을 가져 올 수가 없어서 노가다 코딩을 하던 차 그냥 커스텀클래스로 하나 만들어보자 해서 나온 결과물이다. 요구 사항으로 NSDate를 이용해 오브젝트를 생성하고 NSDate 값을 받아 올 수 있어야 했다.

아래는 실제로 구현한 소스코드이다.
// NSDate를 써야해서 Foundation 프레임워크를 임포트한다.
import Foundation

// MyDatetime 클래스 정의 시작.
class MyDatetime {
    // 멤버 프로퍼티들. 전부 숫자 0으로 초기화 했으니 전부 Int 타입을 가지게 된다.
    var year = 0
    var month = 0
    var day = 0
    var hour = 0
    var minute = 0
    var second = 0
    
    // date 프로퍼티는 setter와 getter를 가지는 연산형 프로퍼티(Computed Property)이다.
    var date: NSDate {
        // setter 정의 시작. 
        // 매개변수 선언이 없기 때문에 입력되는 값은 자동으로 newValue 라는 이름을 가진다.
        set {
            // 아래 코드는 NSDate 오브젝트(newValue)에서 년/월/일/시/분/초를 가져오는 코드다.
            let calendar = NSCalendar.currentCalendar()
            let components = calendar.components(NSCalendarUnit.CalendarUnitYear   |
                                                 NSCalendarUnit.CalendarUnitMonth  |
                                                 NSCalendarUnit.CalendarUnitDay    |
                                                 NSCalendarUnit.CalendarUnitHour   |
                                                 NSCalendarUnit.CalendarUnitMinute |
                                                 NSCalendarUnit.CalendarUnitSecond,
                                                 fromDate: newValue)
            // NSDate 오브젝트에서 뽑은 데이터를 프로퍼티에 넣는다.
            self.year = components.year
            self.month = components.month
            self.day = components.day
            self.hour = components.hour
            self.minute = components.minute
            self.second = components.second
        }
        // getter 정의 시작.
        // getter 이기 때문에 리턴 타입이 생략된다.
        // getter는 당연히 프로퍼티 타입으로 리턴되니까 애초에 명시할 필요도 없다.
        get {
            // 이 클래스의 프로퍼티를 이용해 NSDate 오브젝트를 만들어 내는 코드이다.
            let calendar = NSCalendar.currentCalendar()
            let components = NSDateComponents()
            components.year = self.year
            components.month = self.month
            components.day = self.day
            components.hour = self.hour
            components.minute = self.minute
            components.second = self.second
            
            return calendar.dateFromComponents(components)
        }
    }
    
    // 광역(?) 초기화 메소드
    // 호출 시 파라미터가 길어지는게 싫어져서 언더라인을 써서 별칭 생략을 시켰다.
    // 이렇게 선언하면 오브젝트 생성 시 별명을 안붙여서 생성해도 된다.
    init(_ year: Int, _ month: Int,  _ day: Int, 
         _ hour: Int, _ minute: Int, _ second:Int) {
        self.year = year
        self.month = month
        self.day = day
        self.hour = hour
        self.minute = minute
        self.second = second
    }
    
    // NSDate를 이용하는 초기화 메소드
    init(date: NSDate) {
        // 그냥 프로퍼티에 대입하는 것 같지만
        // date 프로퍼티의 setter가 호출된다.
        self.date = date
    }
    
    // 년/월/일만 받아서 초기화하는 메소드
    convenience init(year:Int, month:Int, day:Int) {
        // 광역(?) 초기화 메소드를 호출한다.
        // convenience를 붙인 이유는 이것 때문.
        self.init(year, month, day, 0, 0, 0)
    }
    
    // 현재 시각으로 초기화 하는 메소드
    convenience init() {
        // NSDate를 이용하는 초기화 메소드를 호출한다.
        // convenience를 붙인 이유는 이것 때문.
        self.init(date: NSDate())
    }
}

이 클래스의 사용 예는 아래와 같다.
// 현재 시간을 기준으로 MyDatetime 오브젝트 생성
let time1 = MyDatetime()

// 특정 년/월/일 기준으로 MyDatetime 오브젝트 생성
let time2 = MyDatetime(year: 2014, month: 6, day: 20)

// 특정 년/월/일/시/분/초 기준으로 MyDatetime 오브젝트 생성
let time3 = MyDatetime(2014, 6, 21, 12, 50, 39)
이런 식으로 오브젝트를 생성 할 수 있다.

MyDatetime 클래스에서 핵심은 date 라는 NSDate 타입의 computed property 이다. computed property 란 setter와 getter를 가지는 프로퍼티인데 이렇게 되면 변수가 아니게 되어서 date 자신을 값을 가질 수 없다. 대신 date를 참조하면 getter가, date에 값을 넣으려 하면 setter가 호출되어서 원하는 결과를 동적으로 얻거나 만들 수 있다.
// 콘솔에 NSDate 타입의 시간데이터가 출력된다.
println(time1.date)

// time2 객체의 데이터가 현재시간 기준으로 변경된다.
time2.date = NSDate()
이런 식으로 setter와 getter를 활용 할 수 있다.


플레이그라운드는 정말 편리한 물건이다. 그나저나 쓰고 보니 이 글이 그다지 유용하진 않은 것 같지만...

위 예제와 관련된 스위프트 글들:
돌아가기: 스위프트(Swift) 가이드

댓글 없음 :