1. Objective-C의 경우
작성한 클래스에 아래와 같은 메소드가 있다고 치자. 이 메소드를 특정 시간 이후에 호출시켜 보고자 한다.
- (void)runningAfter5Seconds {
NSLog(@"runningAfter5Seconds");
}
NSObject에 선언되어 있는 메소드이기 때문에 사실상 거의 모든 클래스에서 이용이 가능한 메소드이다.
[self performSelector:@selector(runningAfter5Seconds) withObject:nil afterDelay:5.0];
코드 내용 만으로도 언제 특정 셀렉터를 호출시키는지 알 수 있다. 위의 경우는 5초 후에 runningAfter5Seconds 메소드를 실행시킨다. 딜레이를 5.0을 줬다는 것에서 밀리세컨드 단위도 무리없이 호출시킬 수 있다고 판단 가능할 것이다.1.2. dispatch_after
dispatch_after 함수는 GCD(Grand Central Dispatch) 기능을 통해 제공되는 함수이다. (메소드가 아니다) 아래와 같이 실행시켜 줄 수 있다.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self runningAfter5Seconds];
});
여기서는 시간단위가 좀 다르니 주의하자. 최신의 Xcode라면 dispatch_after를 입력하면 자동으로 스니펫 자동완성 항목이 뜰 것이다.dispatch_after의 경우 실행시킬 셀렉터가 아닌 코드를 블럭으로 넘기기 때문에 별도로 메소드 등으로 뽑아낼 필요는 없어서 개인적으로 편하다고 생각한다.
참고로 실수가 아닌 정수 초단위로 딜레이를 준다면 좀 더 단순한 방법으로도 호출이 가능하다. 아래 Swift편에서 코드를 올려놨는데, 그냥 시간 부분에 정수를 넣으면 된다. -_-;
1.3. NSTimer
아주 단순하게 NSTimer를 이용해 나중에 실행되도록 스케쥴링 하는 방법이 있다.
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(runningAfter5Seconds) userInfo:nil repeats:NO];
역시 코드 내용만으로 파악 가능할 것이다.마지막의 repeats를 YES로 주게 되면 매 시간 마다 호출되기 때문에 지속적인 스케쥴링에 응용 할 수 있다.
2. Swift의 경우
Swift의 경우 NSObject를 상속받을 경우 거의 비슷하게 이용 할 수 있지만 Selector와 관련해서 Type-Safe를 위배하는 문제가 생기기 때문에 약간 제한이 있다.
동일하게 이번에도 아래와 같은 메소드를 선언해 놓았다고 치고 살펴보자.
func runningAfter5Seconds() {
println("runningAfter5Seconds")
}
2.1. dispatch_after
역시 GCD의 dispatch_after를 활용하는 방법이다.
dispatch_after(5, dispatch_get_main_queue()) {
self.runningAfter5Seconds()
}
dispatch_after의 클로저 인수가 제일 마지막에 오기 때문에 위와 같이 클로져 표현을 좀 더 단순화 시킬 수 있다. 역시나 클로져를 넘기기 때문에 별도의 메소드로 분리할 필요가 없어서 편하다.만약 밀리세컨드 등 좀 더 세분화된 딜레이가 필요하다면 dispatch_time을 이용해보자.
let delay = 5.0 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
self.runningAfter5Seconds()
}
위 코드는 위 Objective-C에서 언급한 dispatch_after와 모양이 비슷하다. :-)Swift 3 의 경우 DispatchQueue 로 단일화 시켜놨기 때문에 이전 코드 그대로는 사용 할 수 없고 아래와 같은 식으로 쓸 수 있다.
let time = DispatchTime.now() + .seconds(5) DispatchQueue.main.asyncAfter(deadline: time) { self.runningAfter5Seconds() }모양세가 이전보단 쓰기 편해졌다.
2.2. NSTimer
Objective-C와 동일하게 NSTimer를 이용 할 수 있다. 다만 이 경우 셀렉터(Selector)를 사용하기 때문에 사용자의 클래스가 NSObject를 상속받고 있어야 한다는 제한이 있다.
NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "runningAfter5Seconds", userInfo: nil, repeats: false)
형식은 동일하다. repeats를 true를 줘서 지속적인 호출을 시키는 것 또한 가능하다. 다만 selector라 불리우는 Swift와는 어울리지 않는 기능을 써야 한다는 점은 좀 안타깝다.관련글: