计时器停止时发出声音 swiftUI Apple Watch
Sound when timer stops swiftUI Apple Watch
我目前正在为 Apple Watch 开发计时器应用程序。当计时器达到 5 秒时,我设法发出声音。只是,当我按下 "done" 时,计时器声音仍在播放,我现在不知道如何停止声音。我正在使用 WKInterfaceDevice.current().play(.success).
我想在 5 秒内按下 "cancel" 按钮和按下 "done" 按钮时停止声音。
我在互联网上找不到任何东西。我认为WKInterfaceDevice没有停止功能。
struct softView: View {
@State var timerVal = 10
var body: some View {
VStack {
if timerVal > 0 {
Text("Time Remaining")
.font(.system(size: 14))
Text("\(timerVal)")
.font(.system(size: 40))
.onAppear(){
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
if self.timerVal > 0 {
self.timerVal -= 1
}
if self.timerVal < 6 {
WKInterfaceDevice.current().play(.success)
}
}
}
Text("Seconds")
.font(.system(size: 14))
Divider()
Spacer()
NavigationLink(destination: ContentView(), label: {Text("Cancel")})
//.cornerRadius(20)
.foregroundColor(Color.red)
.background(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 2)
)
}
else {
NavigationLink(destination: ContentView(), label: {Text("Done")})
.foregroundColor(Color.green)
.background(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.green, lineWidth: 2)
)
}
} .navigationBarHidden(true)
}
你的timer
什么时候知道什么时候停止?
您必须定义停止计时器的事件。这就是 .invalidate
派上用场的地方。
基本示例:
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
对象成为全局对象。
此外,如果要在 timer
为 completed/cancelled 之后弹出 View
,那么我们需要进行更多更改。
这一切都变得有点复杂,但很容易理解。
我建议您将与计时器相关的逻辑分解为 ObservableObject
class 并在 View
.
中使用它
示例:
struct ContentView: View {
@State var isShowingTimer: Bool = false
var body: some View {
NavigationView {
NavigationLink(destination: TimerView(isShowing: $isShowingTimer),
isActive: $isShowingTimer) {
Text("Start Timer")
}
}
}
}
isShowingTimer
控制 TimerView
的 push/pop 事件
- 它作为绑定发送到
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
class 可以发出变化
@Published
变量发出变化信号
@ObservedObject
监听 ObservableObject
上的变化
.onReceive
处理 Publisher
事件。在这种情况下,监听 timerControl.$isComplete
的变化
我目前正在为 Apple Watch 开发计时器应用程序。当计时器达到 5 秒时,我设法发出声音。只是,当我按下 "done" 时,计时器声音仍在播放,我现在不知道如何停止声音。我正在使用 WKInterfaceDevice.current().play(.success).
我想在 5 秒内按下 "cancel" 按钮和按下 "done" 按钮时停止声音。
我在互联网上找不到任何东西。我认为WKInterfaceDevice没有停止功能。
struct softView: View {
@State var timerVal = 10
var body: some View {
VStack {
if timerVal > 0 {
Text("Time Remaining")
.font(.system(size: 14))
Text("\(timerVal)")
.font(.system(size: 40))
.onAppear(){
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
if self.timerVal > 0 {
self.timerVal -= 1
}
if self.timerVal < 6 {
WKInterfaceDevice.current().play(.success)
}
}
}
Text("Seconds")
.font(.system(size: 14))
Divider()
Spacer()
NavigationLink(destination: ContentView(), label: {Text("Cancel")})
//.cornerRadius(20)
.foregroundColor(Color.red)
.background(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 2)
)
}
else {
NavigationLink(destination: ContentView(), label: {Text("Done")})
.foregroundColor(Color.green)
.background(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.green, lineWidth: 2)
)
}
} .navigationBarHidden(true)
}
你的timer
什么时候知道什么时候停止?
您必须定义停止计时器的事件。这就是 .invalidate
派上用场的地方。
基本示例:
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
对象成为全局对象。
此外,如果要在 timer
为 completed/cancelled 之后弹出 View
,那么我们需要进行更多更改。
这一切都变得有点复杂,但很容易理解。
我建议您将与计时器相关的逻辑分解为 ObservableObject
class 并在 View
.
示例:
struct ContentView: View {
@State var isShowingTimer: Bool = false
var body: some View {
NavigationView {
NavigationLink(destination: TimerView(isShowing: $isShowingTimer),
isActive: $isShowingTimer) {
Text("Start Timer")
}
}
}
}
isShowingTimer
控制TimerView
的 push/pop 事件- 它作为绑定发送到
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
class 可以发出变化@Published
变量发出变化信号@ObservedObject
监听ObservableObject
上的变化
.onReceive
处理Publisher
事件。在这种情况下,监听timerControl.$isComplete
的变化