The points for creating a timer app are posted in multiple articles. This article describes the implementation of alarms and vibrations that fire when the timer countdown reaches zero.
You can see the sample code from the URL of the Git repository below. https://github.com/msnsk/Qiita_Timer.git
Import a new library called Audio Toolbox into TimeManager. The AudioToolbox library contains classes, properties, and methods primarily for sound effect sounds, which you can use to break in the alarm sound when the timer countdown reaches zero.
TimeManager.swift
import SwiftUI
import AudioToolbox //Additional import
class TimeManager: ObservableObject {
//(Properties and methods omitted)
}
To use a sound source included in AudioToolbox, you need to specify the SystemSoundID of that sound source. SystemSoundID is a data type, UInt32 typealias.
So, create a property for this data type in the TimeManager class, attach the @Published property wrapper, and assign the ID of the sound source you want to specify by default as the value.
The following resources will help you to find out which ID sounds what. https://github.com/TUNER88/iOSSystemSoundsLibrary
I checked the items of this resource one by one, but it seems to be the notification sound used in a fairly old model of iOS device. We could not find any information about the notification sound that is used by default on recent models. Please note. (If anyone knows, I would appreciate it if you could comment)
The property name was soundID, and I personally felt that it was a comfortable sound source, so I assigned 1151 as the ID.
TimeManager.swift
import SwiftUI
import AudioToolbox //Additional import
class TimeManager: ObservableObject {
//(Other properties omitted)
//Stores the default sound ID with the data type for using the sound source stored in Audio Toolbox
@Published var soundID: SystemSoundID = 1151
//(Method omitted)
}
Import the AudioToolbox library into the MainView as well as the TimeManager in step 1.
The reason for importing AudioToolbox here is that you need to write a method in MainView that sounds an alert when the countdown timer actually reaches 0, and that method is included in AudioToolbox.
MainView.swift
import SwiftUI
import AudioToolbox //Additional import
struct MainView: View {
//(Properties and methods omitted)
}
In the .onReceive modifier of ZStack of MainView, if the remaining time is more than 0 or less than 0, the conditional branch by the if-else statement was already done. Add a method for triggering the alarm sound in the else statement (when the remaining time is 0 or less).
The method is described as follows. In the first argument, specify the soundID property of the TimeManager class prepared earlier in step 2. The second argument is nil.
AudioServicesPlayAlertSoundWithCompletion(self.timeManager.soundID, nil)
MainView.swift
struct MainView: View {
//(Property omitted)
var body: some View {
ZStack {
//(abridgement)
}
//Executes the code in the closure triggered by a timer that is activated every specified time (1 second)
.onReceive(timeManager.timer) { _ in
//The timer status is.Do nothing except running
guard self.timeManager.timerStatus == .running else { return }
//If the remaining time is greater than 0
if self.timeManager.duration > 0 {
//From the remaining time-1 do
self.timeManager.duration -= 1
//When the remaining time is 0 or less
} else {
//Timer status.Change to stopped
self.timeManager.timerStatus = .stopped
//Sound an alarm
AudioServicesPlayAlertSoundWithCompletion(self.timeManager.soundID, nil)
}
}
}
}
Next to the alarm sound is the implementation of vibration. This also uses the same method as the alarm sound. The arguments change.
In the argument, the value of soundID for vibration obtained by the kSystemSoundID_Vibrate property is converted to the SystemSoundID data type and passed.
AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) {}
MainView.swift
struct MainView: View {
//(Property omitted)
var body: some View {
ZStack {
//(abridgement)
}
.onReceive(timeManager.timer) { _ in
guard self.timeManager.timerStatus == .running else { return }
if self.timeManager.duration > 0 {
//(abridgement)
} else {
//(abridgement)
//Sound an alarm
AudioServicesPlayAlertSoundWithCompletion(self.timeManager.soundID, nil)
//Activate vibration
AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) {}
}
}
}
}
Next time, we will create a setting screen that includes alarm and vibration on / off.
Recommended Posts