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

2025. 6. 20. 13:58·iOS 개발/SwiftUI

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

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

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

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


⏱ Timer 설정 및 시작

1. 시간 설정: Picker로 시/분/초 선택

Picker("시", selection: $selectedHour) {
    ForEach(0..<24) { hour in
        Text("\(hour) 시간").tag(hour)
    }
}
.pickerStyle(.wheel)
.frame(width: 100)
  • Picker를 사용해 시, 분, 초를 각각 선택할 수 있게 구성했습니다.
  • 선택된 값은 @Binding으로 상위 뷰(TimerView)와 연결되어 공유됩니다.
@Binding var selectedHour: Int
@Binding var selectedMinute: Int
@Binding var selectedSecond: Int

 

2. 타이머 시작 버튼: 상태값 변경으로 화면 전환

Button {
    timerStart = true
} label: {
    Text("설정하기")
}
  • 설정이 완료되면 timerStart를 true로 변경하여 화면이 TimerSettingView → TimerStartView로 전환됩니다.
  • 이때부터 타이머가 본격적으로 작동하게 됩니다.

 

3. 타이머 시작 시 로직: onAppear로 초기화

.onAppear {
    remainingSeconds = (selectedHour * 3600) + (selectedMinute * 60) + selectedSecond
    targetEndDate = Date().addingTimeInterval(TimeInterval(remainingSeconds))
}
  • 사용자가 설정한 시/분/초 값을 초 단위로 변환하여 remainingSeconds에 저장합니다.
  • 동시에 targetEndDate도 계산하여 종료 예상 시각을 표시합니다.

 

4. 남은 시간 갱신: Timer와 onReceive

.onReceive(timer) { _ in
    guard !timerPause else { return }

    if remainingSeconds > 0 {
        remainingSeconds -= 1
    } else {
        timerPause = true
        timerStart = false
    }
}
  • Timer.publish(...).autoconnect()를 통해 1초마다 remainingSeconds를 감소시키며 타이머가 작동합니다.
  • 0이 되면 자동으로 타이머가 종료되며, 다시 설정 화면으로 돌아가게 됩니다.

❌ Timer 취소

Button {
    timerPause = false
    timerStart = false
} label: {
    Circle()
        .aspectRatio(contentMode: .fit)
        .frame(width: Constants.ControlWidth * 70)
        .foregroundColor(.gray1)
        .overlay {
            Text("취소")
                .font(.system(size: 14))
                .foregroundColor(.iconOn)
        }
}
  • 취소 버튼 클릭 시 실행중인 타이머를 중지 시킴과 동시에 설정화면으로 자동 복귀 됩니다.

⏸ Timer 일시정지 및 재개

1. 상태 변수 선언

@State var timerPause: Bool = false
@State private var remainingSeconds: Int = 0
@State private var targetEndDate: Date? = nil
  • timerPause: 현재 타이머가 일시정지 상태인지 여부
  • remainingSeconds: 현재 남은 시간 (초 단위)
  • targetEndDate: 예상 종료 시각

 

2. 타이머 동작 로직에서 일시정지 처리

.onReceive(timer) { _ in
    guard !timerPause else { return }  // 일시정지 상태면 카운트 X
    
    if remainingSeconds > 0 {
        remainingSeconds -= 1
    } else {
        timerPause = true
        timerStart = false
        // 타이머 종료 처리
    }
}
  • timerPause == true인 경우, .onReceive 내에서 시간 감소 로직을 건너뜁니다.
  • 즉, 일시정지 상태에서는 타이머가 멈춘 듯한 효과를 냅니다.

 

3. 일시정지 / 재생 버튼 구현

Button {
    timerPause.toggle()
    
    if !timerPause {
        // 재생 상태로 전환될 때 종료 예정 시간 다시 설정
        targetEndDate = Date().addingTimeInterval(TimeInterval(remainingSeconds))
    }
} label: {
    Circle()
        .frame(width: Constants.ControlWidth * 70)
        .foregroundColor(.key)
        .overlay {
            Text(timerPause ? "재생" : "일시정지")
                .font(.system(size: 14))
                .foregroundColor(.iconOn)
        }
}

 

4. 버튼 누를 때의 상태 변화

이전 상태 버튼 클릭 후 설명
timerPause = false true 타이머 정지 (시간 감소 중단)
timerPause = true false 타이머 재생 (카운트 재개) + 종료 시각 재계산

 

 

5. 종료 예정 시각 표시

func targetEndDateString() -> String {
    guard let targetEndDate else { return "--:--" }

    let formatter = DateFormatter()
    formatter.dateFormat = "HH:mm"
    return formatter.string(from: targetEndDate)
}
  • 생 시마다 targetEndDate를 다시 갱신하므로, UI 상에 표시되는 시간도 업데이트됩니다.
  • 일시정지 중에는 시간 변동이 없습니다.

🎬 Timer 기능 구현 영상


🧩 마무리

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

history탭 같은 경우에는 기능 자체가 너무 간단하기에 UIKit에서 리뷰한것을 참고하시면 좋을 것 같습니다!

 

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

👉 🔗 GitHub 저장소 바로가기

 

GitHub - woolnd/SwiftUI_MyTodo

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

github.com

 

다음 포스팅에서는 작년 하반기 회고록을 오랜만에 작성해볼까 합니다!

 

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

읽어주셔서 감사합니다 😊

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

[SwiftUI] Memo 기능 리뷰 (Feat. 나만의 Todo)  (4) 2025.06.06
[SwiftUI] Todo 기능 리뷰 (Feat. 나만의 Todo)  (3) 2025.06.02
[SwiftUI] @Published 썼는데도 View가 안 바뀐다?  (0) 2025.05.30
[SwiftUI] Splash & Onboarding 화면 구현 리뷰 (Feat. 나만의 Todo)  (1) 2025.05.26
[SwiftUI] Figma 비율 그대로! 개발하는 Constants 구조체 만들기  (1) 2025.05.24
'iOS 개발/SwiftUI' 카테고리의 다른 글
  • [SwiftUI] Memo 기능 리뷰 (Feat. 나만의 Todo)
  • [SwiftUI] Todo 기능 리뷰 (Feat. 나만의 Todo)
  • [SwiftUI] @Published 썼는데도 View가 안 바뀐다?
  • [SwiftUI] Splash & Onboarding 화면 구현 리뷰 (Feat. 나만의 Todo)
Riu
Riu
안녕하세요 iOS 개발자를 꿈꾸는 Riu입니다. Github: woolnd
  • Riu
    Riu 개발노트
    Riu
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • 티스토리 (2)
      • iOS 개발 (21)
        • SwiftUI (9)
        • UIKit (6)
        • Combine (5)
        • Architecture (1)
      • 알고리즘 (1)
      • 회고록 (2)
  • 블로그 메뉴

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

    • Github
  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바