본문 바로가기
iOS/App

Timer

by 소토리텔러 2023. 12. 21.

DatePicker로 시간을 설정하는 카운트 다운 타이머 앱.

 

 

 

보는 강의가 UIKit으로 구현하여 SwiftUI로 바꿔보려고 했는데 SwiftUI에서는 카운트 다운 모드가 없었다.

이참에 SwiftUI에서 UIKit 사용하는 방법도 공부해야지 룰루~

 

 

Count Down Timer 모드로 설정하고 시간 간격은 1분으로 설정했다. 

Storyboard에서 알아야 할 것은 이 정도.

타이머를 동작시키기 위해서 DispatchSourceTimer를 사용하였다. 

 

var timer: DispatchSourceTimer?
var duration = 60 // DatePicker에서 설정한 시간
var currentSeconds = 0 // 카운트 다운 될 시간

func startTimer() {
    current = duration
    
    if timer == nil {
        timer = DispatchSource.makeTimerSource(queue: .main)
        // 이벤트 핸들러에서 작업하는 내용에 따라 스레드 지정.
	// 1초마다 해야하는 작업이 UI 작업이므로 queue를 main thread로 설정.
       
        timer?.schedule(deadline: .now(), repeating: 1)
        // deadline은 타이머가 시작된지 몇 초 후에 작업을 시작할 건지
        // repeating은 반복 주기로 단위는 sec
        
        timer?.setEventHandler(handler: { [weak self] in
        
            // 타이머가 동작할 때마다 실행되어야 할 작업을 여기에 작성한다.
            // 이 앱에서는 남은 시간을 00:00:00 형태로 표시하고, -> String(format: "%02d", 숫자)
            // 진행 상태를 상태바로 표시하며,
            // 토마토 이미지를 360도씩 돌려준다.    
        
            guard let self = self else { return }
            self.current -= 1 
            self.timerLabel.text = self.formattedTimeString()
            self.progressView.progress = Float(self.currentSeconds) / Float(self.duration)

            startAnimation()

            if self.currentSeconds <= 0 { // 타이머 종료
                self.stopTimer()
            }
        })

        self.timer?.resume() // 타이머 시작
    }
}

 

 

timer의 nil을 체크하는 이유는 타이머를 중단시킬 때 작업을 취소한 후 메모리 해제까지 해주는데

화면이 사라졌을 때도 타이머가 계속 동작하지 않도록 하기 위해서이다.

그리고 주의할 점은 타이머를 중단시킬 때.

 

enum TimerStatus {
    case start
    case pause
    case end
}

func stopTimer() {
    if timerStatus == .pause {
        timer?.resume()
    }

    timer?.cancel()
    timer = nil // 메모리 해제
}

 

 

우선 timer는 resume(), suspend(), cancel() 함수로 각각 실행, 중지, 취소시킬 수 있다.

만약 suspend() 함수를 호출하여 타이머를 일시중지 시켜놓고 cancel() 함수를 호출하면 Runtime Error 발생.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

suspended object의 참조를 해제하려고 하면서 발생한 오류이다.

즉, timer가 동작중일 때 작업을 취소하고 메모리를 해제시키도록 한다. 

Timer의 cancel 여부를 확인할 수 있는 API는 제공하지만, suspend 상태 확인 API는 제공되지 않아

enum으로 Timer의 상태값을 관리하도록 했다.

 

추가로 도움이 된 부분.

보통 view의 isHidden 속성으로 view의 visibility를 조절하는데

자연스러운  변화를 위해 UIView.animate으로 alpha 값을 변경시키면 fade in/out 효과를 줄 수 있다.

 

 

 

 

 

'iOS > App' 카테고리의 다른 글

Delegate: AnyObject  (0) 2023.12.23