iOS programming noob, need help fixing error message - ios

I've recently gotten into iOS development on my own and am building my first app: a Donald Trump soundboard. However, I got an error saying:
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
This is the viewcontroller text:
import UIKit
import iAd
import AVFoundation
class SecondViewController: UIViewController {
// Array of every sound file
let soundFilenames = ["china", "drugs_killers_rapists", "america_great_again", "are_you_gay", "Mexico", "i_just_want_them_to_suffer", "are_you_homosexual", "are_you_surprised", "hes_a_loser", "isis_trump", "fantastic", "the_american_dream_is_dead", "wait_dummies", "special_guy", "I'm_really_rich", "speak_english", "so_probably_i'll_sue_her", "ladies", "ill_build_a_wall", "political_bullshit", "ima_bomb_em", "back_to_univision", "hes_a_pussy", "piece_of_garbage", "i_love_mexicans", "i_love_china", "i_love_saudis", "sit_down", "small_loan", "youre_fired", "lets_see_what_happens", "enough", "congratulations", "why", "are_you_anti_semite", "youre_the_boss", "1mm", "tell_it_like_it_is", "100b", "is_that_right", "hes_insecure", "beaten_up", "I_beat_China_all_the_time", "nonono", "ive_been_watching_you", "motivate_you", "okay_okay", "meatloaf"]
// Array of AudioPlayers for each file
var audioPlayers = [AVAudioPlayer]()
// Outlet for the ScrollView
#IBOutlet weak var ScrollView: UIScrollView!
var bannerView: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Set up scroll view to hold 48 buttons
ScrollView.contentSize.height = 1900
//Set up audio players
for sound in soundFilenames {
do {
// Try to do something
//THIS NEXT LINE IS WHERE THE BREAKPOINT
let url = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(sound, ofType: "mp3")!)
let audioPlayer = try AVAudioPlayer(contentsOfURL: url)
audioPlayers.append(audioPlayer)
}
catch {
// Catch the error that is thrown
audioPlayers.append(AVAudioPlayer())
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(sender: UIButton) {
// Get the audioPlayer that corresponds to the tapped button
let audioPlayer = audioPlayers[sender.tag]
audioPlayer.play()
}
}
Any help will be extremely appreciated.
Edit: fatal error shown at the bottom states:
unexpectedly found nil while unwrapping an Optional value

//Set up audio players
for sound in soundFilenames {
do {
// Try to do something
if let pathOfResource = NSBundle.mainBundle().pathForResource(sound, ofType: "mp3") {
let url = NSURL(fileURLWithPath: pathOfResource)
let audioPlayer = try AVAudioPlayer(contentsOfURL: url)
audioPlayers.append(audioPlayer)
}
}
catch {
// Catch the error that is thrown
audioPlayers.append(AVAudioPlayer())
}
}
Try this updated code.

Related

fatal error: unexpectedly found nil while unwrapping an Optional value on adding audio Swift

I'm trying to add some audio when a button is pressed and the code I use doesnt have any error until I run then I get the 'fatal error: unexpectedly found nil while unwrapping an Optional value' in the out put this line of code:
let url = Bundle.main.url(forResource:sound, withExtension: "mp3")!
This is my entire code just for reference:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let soundFilenames = ["60gs", "check", "dada", "danceforme", "eat", "gods", "irelandbaby", "ko'd", "lefthand", "littlewerp", "nocalls", "precision", "sundaymorning", "surprise", "whothefuckisthatguy", "youlldonothing"]
var audioPlayers = [AVAudioPlayer]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for sound in soundFilenames {
do {
let url = Bundle.main.url(forResource:sound, withExtension: "mp3")!
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayers.append(audioPlayer)
}
catch {
audioPlayers.append(AVAudioPlayer())
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(_ sender: UIButton) {
let audioPlayer = audioPlayers[sender.tag]
audioPlayer.play()
}
}
Error is self-describing: url(forResource: withExtension:) returned nil and force-unwrapping it with ! causes your crash.
To fix this crash re-check that:
all files were added to the project
file names are written right in the code
If the file names are not needed later there is a more reliable way to get all mp3 files in the resources folder
let audioURLs = Bundle.main.urls(forResourcesWithExtension: "mp3", subdirectory: nil)!
for url in audioURLs {
do {
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayers.append(audioPlayer)
}
catch {
audioPlayers.append(AVAudioPlayer())
}
}
or - inspired by Alexander's comment – shortly
let audioURLs = Bundle.main.urls(forResourcesWithExtension: "mp3", subdirectory: nil)!
audioPlayers = audioURLs.flatMap{ try? AVAudioPlayer(contentsOf: $0) }

Play multiple songs in iOS

I wrote this code for iOS to play a song, however I'm not sure how to write the code to play multiple songs.
This is the line of code for a song:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
#IBAction func play(_ sender: AnyObject)
{
player.play()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
do
{
let audioPath = Bundle.main.path(forResource: "Ken", ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//ERROR
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You actually can play it with just two instances of the AVAudioPlayer resp. every sound file needs it's own AVAudioPlayer if you want to play them simultaneously.
I already wrote an answer, so I will post even there is already a correct answer. What palme said is correct. You could use multiple AVAudioPlayer instances to play multiple sounds simultaneously:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let paths = ["a","b"]
var sounds = [AVAudioPlayer]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for path in paths {
do
{
let audioPath = Bundle.main.path(forResource: path, ofType: "mp3")
let player = try AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
sounds.append(player)
}
catch
{
//ERROR
}
}
for sound in sounds {
sound.play()
}
}
}

Swift 3 - AVAudioPlayer is not playing sound

I have a simple program which has one button and its only function is to trigger an sound output.
The app works perfectly when tested on an iOS simulator, but when I test it on an iPhone, the app is not playing any sound. I have tested this on two iPhones.
This was working once upon a time. I don't know if updating to iOS 10 has caused the issue.
Here is my code:
//Code
import UIKit
import AVFoundation
var audioPlayer = AVAudioPlayer()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
}
catch{
print(error)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playSound(_ sender: UIButton) {
audioPlayer.play()
}
}
Would be grateful for any answers.
Thanks.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
audioPlayer.delegate = self
audioPlayer.preparedToPlay()
}
catch{
print(error)
}
}
import UIKit
import AVFoundation
class ViewController: UIViewController {
var btnSound: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
//locate resource
let path = Bundle.main.path(forResource: "sound", ofType: "wav")
let music = URL(fileURLWithPath: path!)
do{
try btnSound = AVAudioPlayer(contentsOf: music)
btnSound.prepareToPlay()
} catch let err as NSError{
print(err.debugDescription)
}
}
}
func playSound(){
if btnSound.isPlaying{
//stop playing sound file if already playing
btnSound.stop()
}
//play sound
btnSound.play()
}
#IBAction func playSound(sender: UIButton){
//call playSound function on pressing the button you attach this function to
playSound()
}

Create a random audio sound generator

Thanks for replying.
I am trying to make a program when I press a button once, two random sounds will play. I can get the random sounds to play if I press the button, but I am looking that if I press the button, the random sound will play differently each time.
I can paste the sounds together to hear them in the sequence I want them, but I would like swift to generate the sounds.
I thought of the AVqueplayer to make it as a playlist. I was thinking this can be like a pair of dice in an analogy. For example, if I were to throw the dice down, the random sounds will occur.
I am still a newbie, and tried to figure this out on my own, because it seemed so simple, but I am out of options now.
Here is what I got so far. This will play a random sound when I press the button each time.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
var sounds = ["sound1", "sound2", "sound3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if event!.subtype == UIEventSubtype.motionShake {
let randomNumber = Int(arc4random_uniform(UInt32(sounds.count)))
let fileLocation = Bundle.main.path(forResource: sounds[randomNumber], ofType: "mp3")
var error: NSError? = nil
do { try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation!))
player.play()
} catch {}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Using the same code, and adding a second random number with matching file location will allow the sounds to play back to back, both being random:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
var sounds = ["sound1", "sound2", "sound3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if event!.subtype == UIEventSubtype.motionShake {
let randomNumber1 = Int(arc4random_uniform(UInt32(sounds.count)))
let randomNumber2 = Int(arc4random_uniform(UInt32(sounds.count)))
let fileLocation1 = Bundle.main.path(forResource: sounds[randomNumber1], ofType: "mp3")
let fileLocation2 = Bundle.main.path(forResource: sounds[randomNumber2], ofType: "mp3")
//var error: NSError? = nil
do {
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation1!))
player.play()
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation2!))
player.play()
} catch {}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

iOS AVAudioPlayer - how to set file path to the pathForResource

i want to play small mp3 file when button is clicked. but not sure how to set the mp3 file in setPathForResources
Here My Code
import UIKit
import AVFoundation
class PlaySoundsViewController: UIViewController {
var coinSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("/sounds/superman", ofType: "mp3")!)
var audioPlayer = AVAudioPlayer()
#IBOutlet weak var PlaySlow: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func PlaySlowAction(sender: UIButton) {
audioPlayer.play()
}
I have added the sounds folder to the project using just drag and drop. but when i click button im getting this error.
audioPlayer.play() Thread 1: EXC_BAD_ACCESS(Code=1,address=0x1c)
You don't need the sounds/ in your path. Just the filename. e.g.
var coinSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("superman", ofType: "mp3")!)
Also fileURLWithPath takes a URL, not a string. You need to convert your NSBundle.mainBundle().pathForResource("superman", ofType: "mp3") to a string first using NSURL(string:).
This is the full setup:
let path = NSBundle.mainBundle().pathForResource("superman", ofType:"mp3")
let fileURL = NSURL(fileURLWithPath: path)
player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
player.prepareToPlay()
player.delegate = self
player.play()
You missed a couple necessary steps in your "PlaySlowAction" method:
#IBAction func PlaySlowAction(sender: UIButton) {
// if the audioPlayer hasn't been set to any sound file yet,
// load it up...
if(audioPlayer.data == nil)
{
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: coinSound, error: &error)
if let actualError = error {
println("An Error Occurred: \(actualError)")
}
}
audioPlayer.prepareToPlay()
audioPlayer.play()
}

Resources