[UIKit] Timer 기능 리뷰 (Feat. 나만의 Todo)

2025. 5. 16. 10:00·iOS 개발/UIKit

오늘은 제가 직접 만든 Todo 앱에 포함된 Timer 기능을 소개하고 리뷰해보려고 해요.

이번 포스팅에서는 총 세 가지 기능을 중심으로 살펴볼게요.

  1. ⏱ Timer 설정 및 시작
  2. ❌ Timer 취소
  3. ⏸ Timer 일시정지 및 재개

하나씩 자세히 확인해볼게요!


⏱ Timer 설정 및 시작

1. PickerView로 시간 선택

원래는 UIDatePicker를 활용하려고 했지만, 초 단위까지는 지원하지 않아 원하는 정밀한 시간 설정이 어려웠습니다.

그래서 사용자에게 시/분/초를 모두 직접 선택할 수 있도록 UIPickerView를 사용해 커스텀 UI를 구성했습니다.

Picker는 세 개의 컴포넌트로 나눴고, 각 요소는 Array(0...59) 또는 Array(0...23)로 구현했습니다.

 

numberOfComponents(in:) -> Int 함수를 활용하여 몇 개의 열(Column) 을 사용할지 지정해요.

pickerView(_:numberOfRowsInComponent:) 함수를 활용하여 몇 개의 선택 항목(Row)이 있는지 알려줍니다.

pickerView(_:widthForComponent:) 함수는 각 열의 너비를 설정할 수 있습니다.

let sec = Array(0...59)
let min = Array(0...59)
let hour = Array(0...23)

extension TimerViewController: UIPickerViewDelegate, UIPickerViewDataSource {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 3 // 시, 분, 초
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch component {
        case 0: return hour.count
        case 1: return min.count
        case 2: return sec.count
        default: return 0
        }
    }
    
    func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return 100
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0: return "\(hour[row]) 시간"
        case 1: return "\(min[row]) 분"
        case 2: return "\(sec[row]) 초"
        default: return nil
        }
    }
}

2.  Timer 시작

사용자가 시간을 선택한 뒤 설정하기 버튼을 누르면 Timer 뷰, 정지, 취소 버튼을 보이게 만들고 시작 버튼은 숨깁니다.
그리고 현재 PickerView의 선택된 행(Row)을 기준으로 selectedHour, selectedMinute, selectedSecond 값을 저장합니다. 

selectedHour = hour[timePicker.selectedRow(inComponent: 0)]
selectedMinute = min[timePicker.selectedRow(inComponent: 1)]
selectedSecond = sec[timePicker.selectedRow(inComponent: 2)]

이 값을 초 단위로 변환한 후, remainingTime 변수에 저장합니다.

remainingTime = selectedHour * 3600 + selectedMinute * 60 + selectedSecond

let endDate = Date().addingTimeInterval(TimeInterval(remainingTime))
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss"
EndTimeLabel.text = "\(formatter.string(from: endDate))"

이렇게 계산한 시간을 기준으로 Timer가 시작되고,

사용자가 선택한 시간에 따라 자동으로 종료 시각도 함께 표시됩니다. (HH:mm:ss 형식)

 

3.  Timer 상세 설명

Timer를 1초 간격으로 반복 실행하여 remainingTime을 줄이고 UI를 갱신하는 함수입니다. 그리고 Timer가 시작되기 전, 남은 시간을 UI에 한 번 표시합니다.

 

1초마다 반복되는 Timer를 생성합니다. weak self로 메모리 누수를 방지하고, remainingTime을 1초씩 줄여나갑니다.

timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
    // 1초마다 실행될 코드
    
    self.remainingTime -= 1
    self.updateTimerLabel()
    
    if self.remainingTime <= 0 {
        self.timer?.invalidate()
        self.timer = nil
        self.timerLabel.text = "00 : 00 : 00"
        self.EndTimeLabel.text = "00:00:00"
        self.stopButton.setTitle("일시 정지", for: .normal)
        self.isPaused = false
        self.updateUI(false)
    }
}
  • withTimeInterval: 1.0 → Timer가 실행되는 간격, 여기서는 1초 간격입니다.
  • repeats: true → 반복 실행 여부, true면 계속 실행, false면 한 번만 실행
  • { [weak self] _ in ... }→ 내부에서  Timer가 1초마다 호출할 코드 블록입니다.

Timer는 1초마다 남은 시간을 줄이며 Timer 라벨을 실시간으로 갱신합니다.

그리고 남은 시간이 0초가 되면 Timer를 종료하고, 라벨을 초기화한 뒤 다시 시간 설정 화면으로 돌아갑니다.


❌ Timer 취소

이 함수는 사용자가 취소 버튼을 눌렀을 때 실행되며, 진행 중이던 Timer를 완전히 중단하고 초기화하는 기능을 담당합니다.

@IBAction func cancelButtonTapped(_ sender: Any) {
        
        updateUI(false)
        timer?.invalidate()
        timer = nil
        timerLabel.text = "00 : 00 : 00"
        EndTimeLabel.text = "00:00:00"
        stopButton.setTitle("일시 정지", for: .normal)
        isPaused = false
    }

⏸ Timer 일시정지 및 재개

이 함수는 사용자가 일시 정지 또는 재생 버튼을 눌렀을 때 호출됩니다. isPaused라는 불리언 값을 기준으로

현재 상태를 판단하고, Timer를 정지하거나 다시 시작하는 역할을 해요.

 

1. 일시 정지 상태에서 재생 누른 경우

Timer가 일시 정지 상태였다면, 상태를 재생 모드로 바꾸고 버튼 텍스트도 다시 "일시 정지"로 변경합니다.

재생 시점 기준으로 다시 종료 시간을 계산해서 UI에 표시해줍니다. 

그리고 현재 Timer가 비어 있을 때만 startCountdown()을 호출하여 중복 실행을 방지합니다.

// ⏯ 재생 상태: 다시 시작
isPaused = false
stopButton.setTitle("일시 정지", for: .normal)

// 종료 시간 재계산
let newEndDate = Date().addingTimeInterval(TimeInterval(remainingTime))
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss"
EndTimeLabel.text = "\(formatter.string(from: newEndDate))"

// 타이머 재시작
// ✅ 타이머가 nil일 때만 재시작 (중복 방지)
if timer == nil {
    startCountdown()
}

 

2. 재생 상태에서 일시 정지 누른 경우

Timer가 실행 중이었다면 Timer를 정지하고 timer 객체를 해제한 뒤 버튼의 텍스트를 "재생"으로 변경해줍니다.

 // ⏸ 정지 상태: 일시정지
isPaused = true
timer?.invalidate()
timer = nil
stopButton.setTitle("재생", for: .normal)

🎬 Timer 기능 구현 영상

 

 


🧩 마무리

오늘은 이렇게 나만의 Todo 앱에 적용한 타이머 기능을 간단히 리뷰해보았습니다!

초 단위까지 세밀하게 설정하기 위해 UIDatePicker 대신 PickerView를 활용한 부분이

이번 타이머 기능 구현의 핵심 포인트였던 것 같아요.

 

📌 전체 코드가 궁금하신 분들은 GitHub 저장소를 참고해주세요:

👉 🔗 GitHub 저장소 바로가기

 

GitHub - woolnd/UIKit_MyTodo

Contribute to woolnd/UIKit_MyTodo development by creating an account on GitHub.

github.com

 

다음 포스팅에서는 앱의 설정 부분에 대해 소개해드릴 예정입니다.

 

앞으로도 꾸준히 기록하며 성장하는 개발자가 되기 위해 달려보겠습니다! 🚀

읽어주셔서 감사합니다 😊

'iOS 개발 > UIKit' 카테고리의 다른 글

[UIKit] 설정 탭 리뷰 (Feat. 나만의 Todo)  (1) 2025.05.20
[UIKit] 녹음 기능 리뷰 (Feat. 나만의 Todo)  (0) 2025.05.12
[UIKit] 메모 기능 구현 리뷰 (Feat. 나만의 Todo)  (1) 2025.05.09
[UIKit] Todo 기능 구현 리뷰 (Feat. 나만의 Todo)  (0) 2025.05.07
[UIKit] Launch & Onboarding 화면 구현 리뷰 (Feat. 음성메모앱)  (2) 2025.05.05
'iOS 개발/UIKit' 카테고리의 다른 글
  • [UIKit] 설정 탭 리뷰 (Feat. 나만의 Todo)
  • [UIKit] 녹음 기능 리뷰 (Feat. 나만의 Todo)
  • [UIKit] 메모 기능 구현 리뷰 (Feat. 나만의 Todo)
  • [UIKit] Todo 기능 구현 리뷰 (Feat. 나만의 Todo)
Riu
Riu
안녕하세요 iOS 개발자를 꿈꾸는 Riu입니다. Github: woolnd
  • Riu
    Riu 개발노트
    Riu
  • 전체
    오늘
    어제
    • 분류 전체보기 (27) N
      • 티스토리 (2)
      • iOS 개발 (21) N
        • SwiftUI (9)
        • UIKit (6)
        • Combine (5)
        • Architecture (1) N
      • 알고리즘 (1)
      • 회고록 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    UIKit
    ios개발
    막자알림서비스
    티스토리
    Combine
    알고리즘
    나만의todo
    안드로이드
    cleanArchitecture
    Architecture
    앗차!
    SWIFT
    SwiftUI
    시작
    figma
    구름톤유니브
    회고록
    ios
    SWIF
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Riu
[UIKit] Timer 기능 리뷰 (Feat. 나만의 Todo)
상단으로

티스토리툴바