3.12 무한루프

Jay·2025년 2월 6일

Level 3 - SingleView App

목록 보기
12/24

Goal

  • 경과한 시간을 뷰에 계속 업데이트 하기.
  • 무한루프 알아보기.

Thinking First

아직까진 start 버튼을 터치해도 뷰에 시간이 바뀌지 않는다.
우선 Stopwatch 가 실행중인지 여부를 알 수 있는 프로퍼티를 만들어 보자.
startTime 을 이용해서 Bool 타입을 리턴하는 연산 프로퍼티가 적당할 것이다.
이 프로퍼티를 통해 실행중이면 뷰에 경과하는 시간을 계속 업데이트 하고 아니라면 멈추도록 해보자.

Making Next

먼저 Stopwatch 클래스에 아래와 같은 프로퍼티를 추가한다.

  var isRunning: Bool {
       return startTime != nil	// startTime 이 nil 이 아니라면 true 리턴
   }

물론 바로 stratTime 을 이용해서 실행여부를 판별할 수도 있지만 가독성을 위해 isRunning 이라는 프로퍼티를 따로 만든것이다.

이제 startButtonTapped 를 다음과 같이 고쳐보았다.

 @IBAction func startButtonTapped(sender: UIButton) {

      stopwatch.start()
      while stopwatch.isRunning {
          print("Updating...")
          timeLabel.text = "\(stopwatch.elapsedTime)"
      }
  }

while 문을 이용해 Stopwatch 가 실행중이라면 레이블에 경과한 시간을 출력하도록 구현한 것이다.
앱을 실행해서 start 버튼을 터치해보자.
예상과 달리 콘솔에는 “Updating…” 이라는 문장을 계속 출력하면서 UI 가 멈춰버리고 아무런 입력을 할 수 없는 상태가 된다.

왜 이런일이 발생할까? 지난 챕터에서 다뤄봤던 런루프라는 개념을 떠올려 보자.
사용자의 입력을 받아 처리할 수 있는 이유는 이 런루프가 메인스레드에서 돌면서 대기하고 있기 때문이다. 그런데 지금은 while 문이 무한 실행되면서 런루프가 계속 그 일을 수행하고 있기 때문에 아무런 처리를 못하는 상태가 되어버린것이다.

한마디로 startButtonTapped 함수가 실행은 되었지만 종료하지 못하므로 어떤 반응도 할 수 없는 상태가 되어 버렸다.
이제 현재시간을 출력할 때 사용했었던 Timer 이용해서 코드를 변경해 보자.

@IBAction func startButtonTapped(sender: UIButton) {
     timer?.invalidate()		//  옵셔널 체이닝으로 현재시간을 출력하는 기존 timer 를 해제한다. 

// 0.1 초마다 updateElapsedTimeLabel 함수가 반복실행되도록 Timer 객체를 구현하여 timer 프로퍼티에 할당한다
     timer = Timer.scheduledTimer(timeInterval: 0.1, target: self,
                          selector: #selector(updateElapsedTimeLabel), userInfo: nil, repeats: true)
     stopwatch.start()
 }

타이머에서 호출하는 경과한 시간에 대한 함수를 구현한다.

  @objc func updateElapsedTimeLabel(timer: Timer) {
       if stopwatch.isRunning {
           timeLabel.text = stopwatch.elapsedTime
       } else {
           timer.invalidate()
       }
   }

Closing

실행해보면 0.1초 간격으로 시간이 업데이트 된다. 그런데 출력되는 형식이 뭔가 이상하다. 다음 챕터에서 보기 편하게 바꿔보도록 하자.

profile
Software Engineer Specialized on iOS

0개의 댓글