[ios] RunLoop 에 대하여

Yoon Yeoung-jin·2022년 8월 25일
0

iOS 개발

목록 보기
9/11

개요

Swift-30-Projects 중 Stopwatch 프로젝트를 클론 코딩을 하면서 아래와 같은 부분을 작성하게 되었다.

RunLoop.current.add(mainStopwatch.timer, forMode: RunLoop.Mode.common)
RunLoop.current.add(lapStopwatch.timer, forMode: RunLoop.Mode.common)

이를 보고 RunLoop에 대해서 찾아보고 정리해보고자 한다.

내용

RunLoop에 대하여.

먼저 애플 공식 문서를 보면 다음과 같은 내용으로 나와있다. (https://developer.apple.com/documentation/foundation/runloop)

* RunLoop 는 입력 소스를 관리를 개체에 대한 프로그매일 방식의 인터페이스다. 
* 개체는 윈도우 시스템으로부터 받은 키보드, 마우스와 같은 이벤트로서 입력소스에 대한 처리를 진행한다. 
* 또한 Timer 에 대한 이벤트도 관리한다.

위 그림에 대한 내용을 정리하면 다음과 같다.

  • input sources: thread 에서 한 루프를 도는 동안, 다른 스레드나 다른 응용프로그램의 비동기 이벤트가 수신된 것을 확인하고, 이벤트 핸들러를 수행한다.
  • Timer source: thread 에서 한 루프를 도는 동안, 예정된 시간이나 반복되는 간격으로 발생하는 동기 이벤트를 수신된 것을 확인하고, 이벤트 핸들러를 수행한다.
  • thread를 생성할 떄 각자 Run loop 가 자동으로 실행되고, Run Loop 의 실행은 개발자가 직접 실행.
    • 특정 Thread가 input source나 timer source를 처리해야하는 경우, RunLoop 에 직접 접근하여 실행해야 가능하다.

코드상의 RunLoop 사용법 .

Swift-30-Projects 중 Stopwatch 프로젝트에서 사용하는 자료구조는 다음과 같다.

class Stopwatch: NSObject {
    var counter: Double         // 단위
    var timer: Timer            // 타이머 객체
    
    override init() {
        counter = 0.0
        timer = Timer()
    }
}

해당 프로젝트에서 RunLoop 사용 루틴은 다음과 같다.

  1. timer 객체에 Timer.scheduledTimer 를 설정한다.
  2. 설정한 timer 객체를 현재 Thread RunLoop 에 등록한다.

해당하는 소스코드 부분은 다음과 같다.

// MARK: - Actions
  @IBAction func playPauseTimer(_ sender: AnyObject) {
    lapRestButton.isEnabled = true
  
    changeButton(lapRestButton, title: "Lap", titleColor: UIColor.black)
    
    if !isPlay {
      unowned let weakSelf = self
      
			/* 타이머 셋팅 */
      mainStopwatch.timer = Timer.scheduledTimer(timeInterval: 0.035, target: weakSelf, selector: Selector.updateMainTimer, userInfo: nil, repeats: true)
      lapStopwatch.timer = Timer.scheduledTimer(timeInterval: 0.035, target: weakSelf, selector: Selector.updateLapTimer, userInfo: nil, repeats: true)
      
			/* 현재 thread RunLoop 에 타이머를 등록한다. */
      RunLoop.current.add(mainStopwatch.timer, forMode: RunLoop.Mode.common)
      RunLoop.current.add(lapStopwatch.timer, forMode: RunLoop.Mode.common)
      
      isPlay = true
      changeButton(playPauseButton, title: "Stop", titleColor: UIColor.red)
    } else {
      
      mainStopwatch.timer.invalidate()
      lapStopwatch.timer.invalidate()
      isPlay = false
      changeButton(playPauseButton, title: "Start", titleColor: UIColor.green)
      changeButton(lapRestButton, title: "Reset", titleColor: UIColor.black)
    }
  }

참고

profile
신기한건 다 해보는 사람

0개의 댓글