Post

Replies

Boosts

Views

Activity

Reply to Alert structure and playing sound
I realized I never got back to this post to show what I ended up with. Like I mentioned before, I was thinking of putting the audio player in shared application data. It looks like this ... import SwiftUI import Observation import os @preconcurrency import AVFoundation @main struct Chain_TimerApp: App { @State private var appData = ApplicationData.shared var body: some Scene { WindowGroup { ContentView() .environment(appData) } } } @Observable class ApplicationData: @unchecked Sendable { var timers: [TimerData] = [] var timerRunningStates: [UUID: Bool] = [:] var isSerial: Bool = false var audioData: AudioData let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Chain Timer", category: "ApplicationData") static let shared: ApplicationData = ApplicationData() . . . For the AudioData structure struct AudioData { var audioPlayer: AVAudioPlayer var sound: String = "classicAlarm" var logger: Logger init(logger: Logger) { self.logger = logger audioPlayer = AVAudioPlayer() } mutating func setSound(sound: String) { let soundPath = Bundle.main.url(forResource: sound, withExtension: "mp3")! // Default do { try audioPlayer = AVAudioPlayer(contentsOf: soundPath) } catch { logger.error("Cannot create player. Error: \(error)") } } func playSound() { if !audioPlayer.isPlaying { // Only play one at a time audioPlayer.play() } } func cancelSound() { audioPlayer.stop() audioPlayer.currentTime = 0 // Reset playback } } Then in my view, I grab application data from the environment and add an alert modifier to a Text view that will use the audio player ... @Environment(ApplicationData.self) private var appData .alert(isPresented: $showAlarmAlert) { appData.audioData.playSound() return Alert(title: Text("Time's Up!"), message: Text("Hit Okay"), dismissButton: .cancel(Text("Okay"), action: { appData.audioData.cancelSound() Putting the audio player in shared data lets any view make use of it. Thanks, MGeek
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’25
Reply to Apple Pie Guided Project: getting error - Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value.
Hi ashtonlalchan, I'm working through the same project and ran into the same issue. I got past it by using the titleLabel property which returns a UILabel. Then I used the UILabel's text property. This is what my letterButtonPressed function looks like: @IBAction func letterButtonPressed(_ sender: UIButton) { sender.isEnabled = false let letterString = sender.titleLabel?.text let letter = Character(letterString!.lowercased()) currentGame.playerGuessed(letter: letter) updateUI() }
Jul ’23
Reply to Alert structure and playing sound
I realized I never got back to this post to show what I ended up with. Like I mentioned before, I was thinking of putting the audio player in shared application data. It looks like this ... import SwiftUI import Observation import os @preconcurrency import AVFoundation @main struct Chain_TimerApp: App { @State private var appData = ApplicationData.shared var body: some Scene { WindowGroup { ContentView() .environment(appData) } } } @Observable class ApplicationData: @unchecked Sendable { var timers: [TimerData] = [] var timerRunningStates: [UUID: Bool] = [:] var isSerial: Bool = false var audioData: AudioData let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Chain Timer", category: "ApplicationData") static let shared: ApplicationData = ApplicationData() . . . For the AudioData structure struct AudioData { var audioPlayer: AVAudioPlayer var sound: String = "classicAlarm" var logger: Logger init(logger: Logger) { self.logger = logger audioPlayer = AVAudioPlayer() } mutating func setSound(sound: String) { let soundPath = Bundle.main.url(forResource: sound, withExtension: "mp3")! // Default do { try audioPlayer = AVAudioPlayer(contentsOf: soundPath) } catch { logger.error("Cannot create player. Error: \(error)") } } func playSound() { if !audioPlayer.isPlaying { // Only play one at a time audioPlayer.play() } } func cancelSound() { audioPlayer.stop() audioPlayer.currentTime = 0 // Reset playback } } Then in my view, I grab application data from the environment and add an alert modifier to a Text view that will use the audio player ... @Environment(ApplicationData.self) private var appData .alert(isPresented: $showAlarmAlert) { appData.audioData.playSound() return Alert(title: Text("Time's Up!"), message: Text("Hit Okay"), dismissButton: .cancel(Text("Okay"), action: { appData.audioData.cancelSound() Putting the audio player in shared data lets any view make use of it. Thanks, MGeek
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jun ’25
Reply to Alert structure and playing sound
My app has multiple timers and I'm getting strange sound behavior. I think I'll try putting a single sound player in the shared application data instead of a view.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’25
Reply to Alert structure and playing sound
Hi Claude31, Thank you for your reply. Your version of playSound worked for me. I'm not sure why the SystemSound option works while AVAudioPlayer does not. I might do some reading on that. Thanks, MGeek.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’25
Reply to Apple Pie Guided Project: getting error - Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value.
Hi ashtonlalchan, I'm working through the same project and ran into the same issue. I got past it by using the titleLabel property which returns a UILabel. Then I used the UILabel's text property. This is what my letterButtonPressed function looks like: @IBAction func letterButtonPressed(_ sender: UIButton) { sender.isEnabled = false let letterString = sender.titleLabel?.text let letter = Character(letterString!.lowercased()) currentGame.playerGuessed(letter: letter) updateUI() }
Replies
Boosts
Views
Activity
Jul ’23