Home > Mobile >  How can I use TimelineView in Swift 5 to refresh a text every second?
How can I use TimelineView in Swift 5 to refresh a text every second?

Time:03-07

I'm pretty new at swift coding and I'm trying to do a very simple project: just a clock that shows the time. I'm using TimelineView to refresh the time every second, but it's not working. This is my code:

import SwiftUI

struct ContentView: View {

@State var hour: Int = Calendar.current.component(.hour, from: Date())
@State var minute: Int = Calendar.current.component(.minute, from: Date())
@State var second: Int = Calendar.current.component(.second, from: Date())


var body: some View {
    ZStack {
        VStack{
            Spacer()
            HStack {
                
                TimelineView(.periodic(from: .now, by: 1)) { timeline in
                    
                    Text(String(hour))
                    Text(String(minute))
                    Text(String(second))
                }
            }
            
            Spacer()
        }


    }
}
}

struct ContentView_Previews: PreviewProvider {
   static var previews: some View {
       Group {
       ContentView()
.previewInterfaceOrientation(.portrait)
       }
   }
}

Since my hour, minute and second variables are @State and I'm using the TimelineView, they should refresh every second, shouldn't they?

I'm very confused and I would appreciate some help. Thank you very much.

CodePudding user response:

You have to observe changes in the timeline.

Here I used onChange and update the value of min, sec, and hour.

struct TimerView: View {
    var date: Date
    
    @State var hour: Int = Calendar.current.component(.hour, from: Date())
    @State var minute: Int = Calendar.current.component(.minute, from: Date())
    @State var second: Int = Calendar.current.component(.second, from: Date())
    
    var body: some View {
        VStack {
            Text(String(hour))
            Text(String(minute))
            Text(String(second))
        }
        .onChange(of: date) { _ in
            second  = 1
            if second > 59 {
                minute  = 1
                second = 0
                if minute > 59 {
                    hour  = 1
                    minute = 0
                    if hour > 23 {
                        hour = 0
                    }
                }
            }
        }
    }
}
struct ContentView: View { var body: some View {
        ZStack {
            VStack{
                Spacer()
                HStack {
                    TimelineView(.periodic(from: .now, by: 1)) { timeline in
                        TimerView(date: timeline.date)
                    }
                }
                Spacer()
            }
        }
    }
}

CodePudding user response:

As the documentation says (enter image description here

To improve formatting, you could use a DateFormatter (enter image description here

CodePudding user response:

Just make your hour-minute-second as computed property not @State

struct ContentView: View {
    var hour: Int {
        Calendar.current.component(.hour, from: Date())
    }
    var minute: Int {
        Calendar.current.component(.minute, from: Date())
    }
    var second: Int {
        Calendar.current.component(.second, from: Date())
    }
    var body: some View {
        TimelineView(.periodic(from: .now, by: 1.0)) { timeline in
            HStack {
                Text(String(hour))
                Text(String(minute))
                Text(String(second))
            }
        }
    }
}
  • Related