Когда ваш timer
знает, когда остановиться?
Вы должны определить событие, когда таймер должен быть остановлен. Вот где пригодится .invalidate
.
Basi c Пример:
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] (timer) in
guard let _weakSelf = self else { timer.invalidate(); return }
_weakSelf.timerVal -= 1
if _weakSelf.timerVal < 0 { //if timer count goes negative then stop timer
timer.invalidate()
} else if _weakSelf.timerVal < 6 {
WKInterfaceDevice.current().play(.success)
}
}
Для большего контроля, т. Е. Если вы хотите остановить timer
, скажем, , нажатие кнопки, тогда мы должны сделать этот объект timer
глобальным.
Кроме того, если вы хотите вывести View
после того, как timer
завершен / отменен, нам нужно внести дополнительные изменения.
Все это немного усложняется, но это легко понять.
Я бы посоветовал вам разбить логи, связанные с таймером c, на класс ObservableObject
и использовать их в вашем View
.
* 1020. * Пример:
struct ContentView: View {
@State var isShowingTimer: Bool = false
var body: some View {
NavigationView {
NavigationLink(destination: TimerView(isShowing: $isShowingTimer),
isActive: $isShowingTimer) {
Text("Start Timer")
}
}
}
}
isShowingTimer
управляет событием push / pop для TimerView
- Оно отправляется как привязка к
TimerView
, поэтому его можно обновить из внутри TimerView
чтобы всплыть.
struct TimerView: View {
//Trigger for popping this view
@Binding var isShowing: Bool
@ObservedObject var timerControl = TimerControl()
var body: some View {
VStack {
Text("\(timerControl.count)")
.onAppear(perform: {
//start timer event
self.timerControl.startTimer(from: 10)
})
.onDisappear(perform: {
//stop timer if user taps on `Back` from the Navigation Bar
self.timerControl.stopTimer()
})
.onReceive(timerControl.$isComplete, //observe timer completion trigger
perform: { (success) in
//hide this view
self.isShowing = !success
})
Text("Cancel")
.onTapGesture(perform: {
//stop timer event
self.timerControl.stopTimer()
})
}
}
}
class TimerControl: ObservableObject {
@Published var count: Int = 0
@Published var isComplete: Bool = false
private var timer: Timer?
init(){}
func startTimer(from count: Int) {
self.count = count
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] (timer) in
guard let _weakSelf = self else { timer.invalidate(); return }
print(_weakSelf.count)
_weakSelf.count -= 1
if _weakSelf.count <= 0 {
_weakSelf.stopTimer()
} else if _weakSelf.count < 6 {
print(">>make some noise here<<")
}
}
}
func stopTimer() {
guard isComplete == false else { return }
timer?.invalidate()
isComplete = true
}
}
ObservableObject
класс может генерировать изменения @Published
переменные испускают сигналы изменений @ObservedObject
прослушивает изменения ObservableObject
.onReceive
событий Publisher
. В этом случае прослушивает изменения на timerControl.$isComplete