Звук, когда таймер останавливается swiftUI Apple Watch - PullRequest
1 голос
/ 25 апреля 2020

Я сейчас работаю над приложением таймера для Apple Watch. Мне удалось получить звук, когда таймер достигает 5 секунд. Только когда я нажимаю «Готово», таймер продолжает звучать, и я не знаю, как остановить звук. Я использую WKInterfaceDevice.current (). Play (.success).

Я хочу остановить звук, когда кнопка «отмена» нажата в течение 5 секунд и когда кнопка «сделано» нажата.

Я не могу найти что-либо в inte rnet. Я думаю, что 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)

}

1 Ответ

1 голос
/ 25 апреля 2020

Когда ваш 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
...