Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger action after x seconds in swiftUI

Tags:

I have been trying to accomplish two main goals that I'm having a headache with. Sorry if it's a simple fix, I am a still bit new to swift/swiftui

  1. trigger an action after a certain time has elapsed.
  2. trigger an @State to change value based on how much time has passed.

I've searched through Stack Overflow and found answers suggesting to use a timer:

struct CurrentDateView : View {     @State var now = Date()      let timer = Timer.publish(every: 1, on: .current, in: .common).autoconnect()      var body: some View {         Text("\(now)")             .onReceive(timer) {                 self.now = Date()             }     } } 

But how would I incorporate this so that something like @State can be used change my value to false after 7.5 seconds has passed:

@State randomTF : Bool = true 

Or a Text("Please Enter Above") to change to Text("Sorry Too Late") after 7.5 seconds has passed

like image 832
Anthney Avatar asked Jan 10 '20 13:01

Anthney


People also ask

How do you delay a task in Swift?

Although there's no direct, built-in way to run a Swift Task with a certain amount of delay, we can achieve that behavior by telling the task to sleep for a given number of nanoseconds before we actually start performing its operation: Task { // Delay the task by 1 second: try await Task.


1 Answers

Create a delay, which then sets the @State property hasTimeElapsed to true when the time has elapsed, updating the view body.

With Swift 5.5 and the new concurrency updates (async & await), you can now use task(_:) like the following:

struct ContentView: View {     @State private var hasTimeElapsed = false      var body: some View {         Text(hasTimeElapsed ? "Sorry, too late." : "Please enter above.")             .task(delayText)     }      private func delayText() async {         // Delay of 7.5 seconds (1 second = 1_000_000_000 nanoseconds)         try? await Task.sleep(nanoseconds: 7_500_000_000)         hasTimeElapsed = true     } } 

See more info about Task.sleep(nanoseconds:) in this answer.


Older versions

Xcode 13.0+ now supports concurrency, backwards compatible! However, here is still the 'old' way to do it:

You can use DispatchQueue to delay something. Trigger it with onAppear(perform:) (which happens when the view first appears). You could also hook the delay up to a Button instead if wanted.

Example:

struct ContentView: View {     @State private var hasTimeElapsed = false      var body: some View {         Text(hasTimeElapsed ? "Sorry, too late." : "Please enter above.")             .onAppear(perform: delayText)     }      private func delayText() {         // Delay of 7.5 seconds         DispatchQueue.main.asyncAfter(deadline: .now() + 7.5) {             hasTimeElapsed = true         }     } } 
like image 114
George Avatar answered Oct 25 '22 13:10

George