Things take time

[SWIFT] 일정 시간 내 반복 함수를 실행할 때 가장 마지막에 호출한 함수 한 번만 호출하기 본문

iOS (기능)

[SWIFT] 일정 시간 내 반복 함수를 실행할 때 가장 마지막에 호출한 함수 한 번만 호출하기

겸손할 겸 2020. 12. 9. 12:03

[개요]

 

제목짓기가 참 애매했는데, 무슨의미냐하면 사용자가 플레이어를 재생하는 도중 앞으로 가기를 위해 더블탭을 눌렀다고 가정하자. 사용자가 더블탭을 5번 눌렀을 때, 최후의 작업은 5번누른 만큼의 시간(10초라 가정할 경우 50초)을 이동하길 원한다.

 

여기서 구현 방법은

1. 더블탭을 누를 때마다 10초를 이동시킨다.

2. 특정시간안에 계속된 연속동작이 들어올 경우, 카운트를 증가시키고 특정 시간이 지나고 연속동작이 들어오지 않았을 때 카운트 * 10초를 해서 해당 플레이어를 이동시킨다.

 

1번이 가장 이상적이긴하겠지만, 상황에 따라 2번을 써야할 때가 있다. 플레이어를 예로 들었지만 애니메이션이 동작하고 있을 때 라던지(애니메이션이 돌고 있는 와중에는 애니메이션을 다시 재시작하지 않기 위함) 등이 있다. 이때 사용하는 함수이다.

 

 

[코드]

        NSObject.cancelPreviousPerformRequests(withTarget: self)
        perform(#selector(sendPlayerDoubleTap), with: self, afterDelay: TimeInterval(0.5))

간단한 소스이다.

예를 들어 더블탭을 할 때 호출되는 함수에 저 두 줄을 넣어주면 된다.

 

순서는 다음과 같다.

 

1. 사용자는 더블탭을 누른다.

2. 위 두 줄이 적힌 함수가 호출된다.

3. cancelPreviousPerformRequests라는 함수는 perform(..afterDelay)가 쓰인 함수를 초기화 시킨다.

4. 0.5초뒤에 sendPlayerDoubleTap이란 함수를 호출시키겠다 선언한다.

5. 사용자가 더블탭을 0.5초안에 또 눌렀다.

6. cancelPreviousPerformRequests에서 4번에서 선언한 함수를 초기화 시킨다.

 

이런 로직이다. 그러므로, sendPlayerDoubleTap이란 함수는 0.5초내에 사용자가 더블탭을 여러 번 클릭했을 경우, 마지막에 누른 더블탭 + 0.5초 후에 함수가 호출되는 것이다.

 

중복된 함수가 일정 시간이 지연된 뒤에 호출되는 경우, 한 번만 호출할 때 사용하는 방법이다.

 

cancelPreviousPerformRequests 함수의 주의점은 현재 target으로 등록된 애들이 대상이다. 즉, self로 등록한 perform의 afterDelay함수들은 다 제거 시키는 것이지만, 현재 돌고 있는.. looping중인 perform만 종료시킨다. 즉, 현재 perform할 예정인 애들이 아닌 애들은 종료되지 않는다.

 

 

[또 다른 방법]

perform의 afterDelay가 보인다면, 한 가지 생각나는 것이 있다.

DispatchQueue.main.asyncAfter(deadline: .now() + playerContinuousDelay, execute: {
})

즉, 메인쓰레드를 통해 일정 시간이 지났을 때 execute하면 되는 것이다. 이때는 cancelPreviousPerformRequests라는 함수가 먹히지 않으므로, 사용방법은 execute안에 flag나 검사 로직등을 세워서 일정 시간안에 또 호출되었을 경우 return시키면 된다.