Search code examples
swiftuiviewtimer

SwiftUI with a Timer


I am new to learning SwiftUI, I want to add a Timer to a VIEW in SwiftUI, why can't I update "SomeTEXTinVIEW", what error do I not understand, how can I update an @State variable that is not inside Colsure ?

Cannot use instance member 'SomeTEXTinVIEW' within property initializer; property initializers run before 'self' is available

    @State var SomeTEXTinVIEW: String = "NoValue"
    
    var timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { _ in
        
        SomeTEXTinVIEW = String("Example Result")  // With Error, can not update
        
    }

.... FOLLOW UP ....

I originally planned that the Timer could be paused. I changed the Code suggested by Marcy, but there was an error. Please tell me where I went wrong. Thanks in advance for help.

    struct ContentView: View {
    @State var someTextInView: Int = 0
    
    var timer = Timer()  // Comment this line !!!
    @State var timer = Timer()
    
    var body: some View {
        VStack {
            Text(String(someTextInView))
            
            Button("Re-Start", action: {
                timer.fireDate = Date.init(timeIntervalSinceNow: 0.01)})

            Button("Pause / Stop", action: {
                timer.fireDate = Date.distantFuture
                timer.invalidate()  // Comment this line !!!
            })
        }
        .onAppear {
            timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
                someTextInView += 1
            }
        }
    }
}

The following is executable without errors (Just for references)

    struct ContentView: View {
    @State var someTextInView: Int = 0
    
    var body: some View {
            Text(String(someTextInView))
        .onAppear {
            Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
                someTextInView += 1
            }
        }
    }
}

Solution

  • The error generated is:

    Cannot use instance member 'SomeTEXTinVIEW' within property initializer; property initializers run before 'self' is available

    The timer property can't use SomeTEXTinVIEW because it hasn't been created yet. Structs(and classes and enums) are unordered lists of properties and methods. So the struct's property declarations can't rely on the existence of another of the struct's properties in that situation.

    But the timer could be executed something like this instead:

    struct ContentView: View {
        @State var someTextInView: String = "NoValue"
        
        var body: some View {
            Text(someTextInView)
            .onAppear {
                Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { _ in
                    someTextInView = "Example Result"
                }
            }
        }
    }
    

    I'd recommend that the property SomeTEXTinVIEW be written in camel case like this someTextInView. That's the accepted style in Swift and will makes the code easier to read as it helps to distinguish properties from types.

    Converting "Example Result" to a string is unnecessary because it is already a string.