getting unresolved identifier 'self' in SwiftUI code trying to use Timer.scheduledTimer

和自甴很熟 提交于 2019-12-13 17:26:26

问题


In SwiftUI I'm noting to use a Timer that:

Try 1 - This doesn't work as get "Use of unresolved identifier 'self'"

var timer2: Timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {
    self.angle = self.angle + .degrees(1)
}

Try 2 - Works, but have to put in an "_ = self.timer" to start it later

var timer: Timer {
    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {_ in
        self.angle = self.angle + .degrees(1)
    }
}
// then after need to use " .onAppear(perform: {_ = self.timer}) "

Is there a way to get my Try1 working? That is where in a SwiftUI file I can create the timer up front? Or actually where in SwiftUI would one normally start and stop the timer? i.e. where are lifecycle methods

Whole file:

import SwiftUI

struct ContentView : View {

    @State var angle: Angle = .degrees(55)

//    var timer2: Timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {
//        self.angle = self.angle + .degrees(1)
//    }

    var timer: Timer {
        Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {_ in
            self.angle = self.angle + .degrees(1)
        }
    }

    private func buttonAction() {
        print("test")
        self.angle = self.angle + .degrees(5)
    }

    var body: some View {
        VStack{
            Text("Start")
            ZStack {
                Circle()
                    .fill(Color.blue)
                    .frame(
                        width: .init(integerLiteral: 100),
                        height: .init(integerLiteral: 100)
                    )
                Rectangle()
                    .fill(Color.green)
                    .frame(width: 20, height: 100)
                    // .rotationEffect(Angle(degrees: 25.0))
                    .rotationEffect(self.angle)
            }
            Button(action: self.buttonAction) {
                Text("CLICK HERE")
            }
            Text("End")
        }
         .onAppear(perform: {_ = self.timer})

    }
}

回答1:


It isn't clear to me that you need a timer for your example, but since there is a great deal of misinformation out there about how to include a Timer in a SwiftUI app, I'll demonstrate.

The key is to put the timer elsewhere and publish each time it fires. We can easily do this by adding a class that holds the timer as a bindable object to our environment (note that you will need to import Combine):

class TimerHolder : BindableObject {
    var timer : Timer!
    let didChange = PassthroughSubject<TimerHolder,Never>()
    var count = 0 {
        didSet {
            self.didChange.send(self)
        }
    }
    func start() {
        self.timer?.invalidate()
        self.count = 0
        self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { 
            _ in
            self.count += 1
        }
    }
}

We will need to pass an instance of this class down through the environment, so we modify the scene delegate:

window.rootViewController = 
    UIHostingController(rootView: ContentView())

becomes

window.rootViewController = 
    UIHostingController(rootView: ContentView()
        .environmentObject(TimerHolder()))

Finally, lets put up some UI that starts the timer and displays the count, to prove that it is working:

struct ContentView : View {
    @EnvironmentObject var timerHolder : TimerHolder
    var body: some View {
        VStack {
            Button("Start Timer") { self.timerHolder.start() }
            Text(String(self.timerHolder.count))
        }
    }
}


来源:https://stackoverflow.com/questions/56895459/getting-unresolved-identifier-self-in-swiftui-code-trying-to-use-timer-schedul

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!