2

i am very new to iOS coding. I am trying to build an app for my kids. I have some pictures with animals and the sound that these animals do. I've managed to code the app: each time I tap on the screen, the picture changes and the sound related to the picture changes also. After some time, I get this error and the app hangs:

2020-05-01 12:21:31.111411+0200 Animals For Kids[1758:47571] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/andreitomescu/Desktop/iOS Developing - Udemy/Proiecte diverse/Animals For Kids/Animals For Kids/ViewController.swift, line 21

the code at line 21 is:

    func playSound(animalName: String) {
    let url = Bundle.main.url(forResource: animalName, withExtension: "wav", subdirectory: "Sounds")
    **player = try! AVAudioPlayer(contentsOf: url!)** / this is the line where the error points to
    player.play()
}

Can you please help me figure this one out?

enter image description here

Code part 1:

@IBAction func imageButton(_ sender: UIButton) {

    func playSound(animalName: String) {
        let url = Bundle.main.url(forResource: animalName, withExtension: "wav", subdirectory: "Sounds")
        player = try! AVAudioPlayer(contentsOf: url!)
        player.play()
    }

Code part 2:

 let fileManager = FileManager.default
    let bundleURL = Bundle.main.bundleURL
    let assetURL = bundleURL.appendingPathComponent("Pictures")

    do {
        let contents = try fileManager.contentsOfDirectory(at: assetURL, includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey], options: .skipsHiddenFiles)

      for item in contents
      {
        fileName.append(String(item.lastPathComponent.dropLast(4)))

        animalName = fileName.randomElement()!

Code part 3:

 let imageName = animalName
        let image = UIImage(named: imageName)
        let imageView = UIImageView(image: image!)
        imageView.frame = CGRect(x: 0, y: 360, width: 414, height: 414)
        view.addSubview(imageView)

      }
    }
    catch let error as NSError {
      print(error)
    }
   // playSound(animalName: animalName)
    print(animalName)
Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
  • It would be useful to see some more of your code - particularly how you get the new picture and sound url with each tap. – Tom May 01 '20 at 11:07
  • Hi, I updated the post with a screenshot of my code. Thanks – Andrei Tomescu May 01 '20 at 11:44
  • As the other posts have stated, it's likely because an image or sound doesn't exist for one of the animal names. By way of debugging I would add a print(animalName) to the imageButton method to find out which animalName is causing the app to crash. You can then investigate further from there - it may be an incorrect file name or simply missing altogether. – Tom May 01 '20 at 11:56
  • What is `animalName` when it crashes? Maybe you only have 6 animal names, but call this function more than 6 times. – koen May 01 '20 at 11:57
  • Hi koen, I have an array with all animal names. From this array I pick randomly one and I display the picture and the associated sound. Without the sound function the app works endlessly. – Andrei Tomescu May 01 '20 at 13:40
  • check my answer... and update your code ... remove force castinng – Jawad Ali May 01 '20 at 17:50

2 Answers2

2

It's due to force-unwrapping a nil value as error clearly states that

error: Unexpectedly found nil while unwrapping an Optional value

But why did the app worked for aprox 8 taps and then suddenly crashed? All the files are in the URL ?

Its because first 8 urls are good ad load 9th url is corrupted that specified URL location or couldn't load the contents.

So checkout the url on which your app crash ..

Remove force casting from your code .. update play sound method with the following and check print statement and let me know

var player: AVAudioPlayer?
     func playSound(animalName: String) {

          guard let url = Bundle.main.url(forResource: animalName, withExtension: "wav", subdirectory: "Sounds") else {
                print("path not correct")
                return
          }
           do {
            player = try AVAudioPlayer(contentsOf: url)
            player?.play()
           } catch {
            print("url is not correct")
          }

        }
Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
0

It's due to force-unwrapping a nil value. It could be either due to no resource at the specified URL location or couldn't load the contents.

To understand more on the crash please check this link

Vikram Parimi
  • 777
  • 6
  • 29