计时器停止时发出声音 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
  • 的变化