⭐️Timer 타이머⭐️
지난 시간 컴바인 개념을 떠올리며.. 타이머도 Publisher이다.
일정한 시간 간격마다 이벤트를 생성하기 때문이다.
이를 활용해서 카운트 다운, 시계, 디데이, 애니메이션, 자동 스와이프 등을 구현할 수 있다.
Timer
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
every - 타이머 이벤트가 발생하는 간격 (여기서는 1초 마다)
on - 타이머 이벤트가 실행되는 큐를 지정. (여기서는 UI 업데이트 관련 작업을 하기에 메인 스레드로 지정)
in - 타이머 이벤트를 처리할 스케줄러(scheduler)를 지정. .common은 일반적인 실행 우선순위를 가짐.
(타이머 이벤트가 기본 실행 우선순위로 처리되어 일반적인 작업과 함께 실행될 수 있음)
.autoconnect() - 타이머 자동 연결. (타이머가 생성되면 자동으로 실행됨)
카운트 다운
10부터 1초에 1씩 줄어들며 시간이 다 되면 'Time's Up' 텍스트가 보임.
// Created by Toughie on 2023/06/13.
//
import SwiftUI
struct TimerPrac: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var count: Int = 10
@State var finishedText: String?
var body: some View {
ZStack {
Text(finishedText ?? "\(count)")
}
.onReceive(timer) { _ in
if count <= 1 {
finishedText = "Time's Up!"
} else {
count -= 1
}
}
}
}
.onReceive(_ publisher:perform:)
Publisher의 값을 수신해서 해당 값에 대한 동작을 수행하는데 사용되는 메서드.
timer Publisher를 구독하고, 각 타이머 이벤트를 받았을 때 실행될 클로저를 정의한 것이다.
여기서는 따로 수신받은 값을 활용하지 않기에 와일드카드 처리함.
시계(DateFormatter)
1초씩 시간 확인 가능한 시계
// Created by Toughie on 2023/06/13.
//
import SwiftUI
struct Clock: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var currentData: Date = Date()
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter
}
var body: some View {
ZStack {
Text(dateFormatter.string(from: currentData))
}
.onReceive(timer) { value in
currentData = value
}
}
}
Computed Property 활용해서 DateFormatter 초기화
날짜, 시간 표기 방식을 다양하게 설정할 수 있다. (short, medium, long, full)
디데이(타이머 2)
카운트다운 연장선으로 몇시간 뒤, 며칠 뒤 까지 얼마나 남았는지 체크 가능
// Created by Toughie on 2023/06/13.
//
import SwiftUI
struct Timer2: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var timeRemaining: String = ""
let futureDate: Date = Calendar.current.date(byAdding: .hour, value: 1, to: Date()) ?? Date()
func updateTimeRemaining() {
let remaining = Calendar.current.dateComponents([.hour, .minute, .second], from: Date(), to: futureDate)
let hour = remaining.hour ?? 0
let minute = remaining.minute ?? 0
let second = remaining.second ?? 0
timeRemaining = "\(hour): \(minute): \(second)"
}
var body: some View {
ZStack {
Text(timeRemaining)
.font(.system(size: 100, weight: .semibold, design: .rounded))
.foregroundColor(.gray)
.lineLimit(1)
.minimumScaleFactor(0.1)
}
.onReceive(timer) { value in
updateTimeRemaining()
}
}
}
let futureDate
-> 현재 날짜에서 1시간 만큼 더한 날짜를 나타냄 (by adding: .day)면 일 단위로 더하기 가능
func updateTimeRemaining()
현재 시간 Date()와 futureDate 사이의 시간 간격을 계산하고 시간, 분, 초 컴포넌트로 분해해서
문자열 보간법을 활용해 뷰에 표기하는 방식
로딩 애니메이션
로띠에서 흔히 보이는 공이 통통 거리는 로딩 애니메이션
// Created by Toughie on 2023/06/13.
//
import SwiftUI
struct TimerAnimation: View {
let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()
@State var count: Int = 0
var body: some View {
ZStack {
HStack(spacing: 15) {
Circle()
.fill(Color.red.opacity(0.5))
.offset(y: count == 1 ? -20 : 0)
Circle()
.fill(Color.green.opacity(0.5))
.offset(y: count == 2 ? -20 : 0)
Circle()
.fill(Color.blue.opacity(0.5))
.offset(y: count == 3 ? -20 : 0)
}
.frame(width: 150)
.foregroundColor(.blue)
.onReceive(timer) { value in
withAnimation(.easeIn(duration: 0.5)) {
count = count == 3 ? 0 : count + 1
}
}
}
}
}
총 3초동안 진행되는 애니메이션, 매 초마다 각 원의 오프셋을 조정해주는 방식(withAnimation)
count = count == 3 ? 0 : count + 1
삼항 연산자 활용 할당방식 참고.
3초가 됐을때 count를 다시 0으로 바꿔주고 1씩 계속 증가 시킴
자동으로 탭뷰 넘기기
배너? 같은 느낌을 줄 때 활용할 수 있을듯
// Created by Toughie on 2023/06/13.
//
import SwiftUI
struct AutoTabView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var count: Int = 1
var body: some View {
ZStack {
TabView(selection: $count) {
Rectangle()
.foregroundColor(.red)
.overlay(Text("안").font(.largeTitle).foregroundColor(.white))
.tag(1)
Rectangle()
.foregroundColor(.green)
.overlay(Text("녕").font(.largeTitle).foregroundColor(.white))
.tag(2)
Rectangle()
.foregroundColor(.blue)
.overlay(Text("하").font(.largeTitle).foregroundColor(.white))
.tag(3)
Rectangle()
.foregroundColor(.orange)
.overlay(Text("세").font(.largeTitle).foregroundColor(.white))
.tag(4)
Rectangle()
.foregroundColor(.mint)
.overlay(Text("요").font(.largeTitle).foregroundColor(.white))
.tag(5)
}
.tabViewStyle(.page)
.frame(height: 200)
}
.onReceive(timer) { value in
count = count == 5 ? 1 : count + 1
}
}
}
원하는 간격에 따라 특정한 작업을 수행할 때 Timer를 활용할 수 있다! 정도로 요약 할 수 있겠다.
'SwiftUI > SwiftUI(Intermediate)' 카테고리의 다른 글
21. FileManager 파일매니저 (0) | 2023.06.15 |
---|---|
20. @Published / Subscriber / Combine (0) | 2023.06.14 |
18. Combine 컴바인 .feat JSON (0) | 2023.06.13 |
17. JSON Download with @escaping (0) | 2023.06.12 |
16. Codable, JSON, Encodable, Decodable (0) | 2023.06.12 |