Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make view to update when current time passes the threshold in SwiftUI?

Tags:

swiftui

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.

like image 949
user482594 Avatar asked Oct 15 '25 12:10

user482594


1 Answers

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!")
        }
        
    }
}
like image 94
Hadi Avatar answered Oct 18 '25 08:10

Hadi