My app fetches a model data from a remote server. This model has a field with epoch value where SwiftUI view should show different views based on whether or not current time has passed the epoch.
Model looks something like below.
struct Order: Decodable {
var expireAt : Int
func isExpired() -> Bool {
let epoch = Int(Date().timeIntervalSince1970)
return expireAt < epoch
}
}
And view looks something like below.
struct OrderView: View {
@EnvironmentObject var rs : RemoteService
var body: some View {
if rs.hasOrder() {
NavigationView {
VStack {
if rs.Order != nil && rs.Order!.isExpired() {
Text("Your order has expired")
} else {
Text("Your order has not expired.")
}
}
}
} else {
Text("You don't have order yet!")
}
}
}
What I want to achieve is that view gets updated automatically as soon as current epoch time passes the model's expireAt
threshold.
What is the best way to achieve that? Should I use Timer
or ObservableObject
, or both? For instance, using ObservableObject
seems to require use of Class
instead of Struct
for the model, and I am not sure if that is what I want to achieve.
What you can do is to create a timer that runs every 1 sec for example, and use onReceive
method to update your private state, like this:
class AppConfig: ObservableObject {
@Published var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
}
struct OrderView: View {
@EnvironmentObject var rs : RemoteService
@EnvironmentObject var appConfig : AppConfig
@State private var showExpiredText: Bool = false
var body: some View {
if rs.hasOrder() {
NavigationView {
VStack {
if showExpiredText {
Text("Your order has expired")
} else {
Text("Your order has not expired.")
}
}
}
.onReceive(appConfig.timer) { _ in
if rs.Order != nil && rs.Order!.isExpired() {
showExpiredText = true
} else {
showExpiredText = false
}
}
} else {
Text("You don't have order yet!")
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With