Timer and onReceive in SwiftUI
Updated:
Timer and onReceive in SwiftUI
Timer into our view and then every time that timer goes off we’re going to do something on the screen. So we’re going to startoff very simply by just putting the current time on the screen and every second it’s going to update the time
A timer is actually a publisher it is an object that publishes values over time that’s what a publisher is and then we’re going to use the on receive call which is a really convenient swiftUI function so that we can listen to that publisher also known as subscribing
// Current time Example
import SwiftUI
struct TimerBootCamp: View {
// MARK: - PROPERTY
let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
// Current Time
@State var currentDate: Date = Date()
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
// formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter
}
// MARK: - BODY
var body: some View {
ZStack {
// background
RadialGradient(
gradient: Gradient(colors: [Color.purple, Color.blue]),
center: .center,
startRadius: 5,
endRadius: 500)
.ignoresSafeArea()
// Foreground
Text(dateFormatter.string(from: currentDate))
.font(.system(size: 100, weight: .semibold, design: .rounded))
.foregroundColor(.white)
.lineLimit(1)
.minimumScaleFactor(0.1)
} //: ZSTACK
.onReceive(timer) { value in
currentDate = value
}
}
}
// CountDown example
struct TimerBootCamp: View {
// MARK: - PROPERTY
let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
// Countdown
@State var count: Int = 10
@State var finishedText: String? = nil
// MARK: - BODY
var body: some View {
ZStack {
// background
RadialGradient(
gradient: Gradient(colors: [Color.purple, Color.blue]),
center: .center,
startRadius: 5,
endRadius: 500)
.ignoresSafeArea()
// Foreground
Text(finishedText ?? "\(count)")
.font(.system(size: 100, weight: .semibold, design: .rounded))
.foregroundColor(.white)
.lineLimit(1)
.minimumScaleFactor(0.1)
} //: ZSTACK
.onReceive(timer) { _ in
if count <= 1 {
finishedText = "Wow!"
} else {
count -= 1
}
}
}
}
// Countdown to date
struct TimerBootCamp: View {
// MARK: - PROPERTY
let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
// Countdown to date
@State var timeRemaining: String = ""
let futureDate: Date = Calendar.current.date(byAdding: .hour, value: 1, to: Date()) ?? Date()
// MARK: - BODY
var body: some View {
ZStack {
// background
RadialGradient(
gradient: Gradient(colors: [Color.purple, Color.blue]),
center: .center,
startRadius: 5,
endRadius: 500)
.ignoresSafeArea()
// Foreground
Text(timeRemaining)
.font(.system(size: 100, weight: .semibold, design: .rounded))
.foregroundColor(.white)
.lineLimit(1)
.minimumScaleFactor(0.1)
} //: ZSTACK
.onReceive(timer) { _ in
updateTimeRemaing()
}
}
// MARK: - FUNCTION
func updateTimeRemaing() {
let remaining = Calendar.current.dateComponents([.minute, .second], from: Date(), to: futureDate)
let minute = remaining.minute ?? 0
let second = remaining.second ?? 0
timeRemaining = "\(minute) minutes \(second) seconds"
}
}
// Animation counter
struct TimerBootCamp: View {
// MARK: - PROPERTY
let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()
// Animation counter
@State var count: Int = 0
// MARK: - BODY
var body: some View {
ZStack {
// background
RadialGradient(
gradient: Gradient(colors: [Color.purple, Color.blue]),
center: .center,
startRadius: 5,
endRadius: 500)
.ignoresSafeArea()
// Foreground
HStack {
Circle()
.offset(y: count == 1 ? -20 : 0)
Circle()
.offset(y: count == 2 ? -20 : 0)
Circle()
.offset(y: count == 3 ? -20 : 0)
} //: HSTACK
.frame(width: 150)
.foregroundColor(.white)
} //: ZSTACK
.onReceive(timer) { _ in
withAnimation(.easeInOut(duration: 0.5)) {
count = count == 3 ? 0 : count + 1
}
}
}
}
// automatic Tabview
struct TimerBootCamp: View {
// MARK: - PROPERTY
let timer = Timer.publish(every: 2.0, on: .main, in: .common).autoconnect()
// Animation counter
@State var count: Int = 1
// MARK: - BODY
var body: some View {
ZStack {
// background
RadialGradient(
gradient: Gradient(colors: [Color.purple, Color.blue]),
center: .center,
startRadius: 5,
endRadius: 500)
.ignoresSafeArea()
// Foreground
TabView(selection: $count) {
Rectangle()
.foregroundColor(.red)
.tag(1)
Rectangle()
.foregroundColor(.blue)
.tag(2)
Rectangle()
.foregroundColor(.green)
.tag(3)
Rectangle()
.foregroundColor(.orange)
.tag(4)
Rectangle()
.foregroundColor(.pink)
.tag(5)
} //: TAB
.frame(height: 200)
.tabViewStyle(PageTabViewStyle())
} //: ZSTACK
.onReceive(timer) { _ in
withAnimation(.spring()) {
count = count == 5 ? 1 : count + 1
}
}
}
}
🗃 Reference
SwiftUI Thinking - https://www.youtube.com/watch?v=ymXRX6ZB-J0&list=PLwvDm4VfkdpiagxAXCT33Rkwnc5IVhTar&index=26
Leave a comment