1

I am trying to add music to a game I created. But I am getting the error:

"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value.

I found another post on Stack Overflow (What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?), but I do not understand how this applies to my code.

This is my code:

import UIKit
import SpriteKit
import GameplayKit
import AVFoundation

class GameViewController: UIViewController {
    var player:AVAudioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        do {
            let audioPath = Bundle.main.path(forResource: "HomeSoundtrack", ofType: "m4a")
            try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
        }
        catch {
        }

        let session = AVAudioSession.sharedInstance()

        do {
            try session.setCategory(AVAudioSessionCategoryPlayback)
        }
        catch {
        }

        player.play()

        if let view = self.view as! SKView? {
            // Load the SKScene from 'GameScene.sks'
            if let scene = SKScene(fileNamed: "GameScene") {
                // Set the scale mode to scale to fit the window
                scene.scaleMode = .aspectFill

                // Present the scene
                view.presentScene(scene)
            }

            view.ignoresSiblingOrder = true

            view.showsFPS = false
            view.showsNodeCount = false
        }
    }

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return .allButUpsideDown
        } else {
            return .all
        }
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Aidan
  • 89
  • 1
  • 2
  • 11
  • 1
    First locate where/identify which line. That's an important step in debugging. – Larme May 26 '18 at 15:44
  • 1
    Go through the answers to the question you linked. You first need to find the line of code causing the error. Once you know which line is the problem and you then know which variable is `nil`, you can determine how to fix it. – rmaddy May 26 '18 at 15:46
  • 1
    Side note - do not use `NSURL` in Swift, use `URL`. – rmaddy May 26 '18 at 15:48

2 Answers2

1

Optional value is value that may be contain nil if you want to get its value you have to wrapping it

but use safe wrapping not force wrapping !

check this line

let audioPath = Bundle.main.path(forResource: "HomeSoundtrack", ofType: "m4a")

audioPath is An Optional so it may contain nil value assume that you write HomeSoundtrack Wrong or file not found then audioPath will be nil

then you force wrapping ! it . in this line if audioPath is nil then it will crash

try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)

can be done safe

  let audioPathURL =  Bundle.main.url(forResource: "HomeSoundtrack", withExtension: "m4a")
        {
            do {
                player = try AVAudioPlayer(contentsOf:  audioPathURL)
            }  catch {
                print("Couldn't load HomeSoundtrack file")

            }
        }
Abdelahad Darwish
  • 5,969
  • 1
  • 17
  • 35
  • 1
    1. Loading a path from the bundle should not fail. It should be force-unwrapped. If it crashes then you know you made a mistake such as forgetting to target the file. No need for the `if let` getting the path. 2. Use `Bundle.main.url` to directly get a URL. – rmaddy May 26 '18 at 16:20
  • Sorry @rmaddy i didn't understand this line (`1. Loading a path from the bundle should not fail. It should be force-unwrapped`) , also i update my answer – Abdelahad Darwish May 26 '18 at 16:26
  • Add a `!` to the end of the `let audioPath...` line to force-unwrap the optional. You want it to crash during development if the file isn't found. – rmaddy May 26 '18 at 16:28
  • Yes i got it better to crash during development – Abdelahad Darwish May 26 '18 at 16:29
0

In your code you are force unwrapping an optional using ! which can cause this error if what you are force unwrapping happens to be nil. In

try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)

this could cause the error if the audioPath is nil, abetter to do it would be

//If this line errors, there is a problem with finding HomeSoundtrack.m4a in the bundle
let audioPathURL: URL =  Bundle.main.url(forResource: "HomeSoundtrack", withExtension: "m4a")!
do {
    player = try AVAudioPlayer(contentsOf:  audioPathURL)
} catch {
    print("Couldn't load HomeSoundtrack file with error: \(error)")
}

or in

if let view = self.view as! SKView?

this if let should probably look like

if let view: SKView = self.view as? SKView {
    //Game stuff
}
Pasosta
  • 825
  • 3
  • 13
  • 22
  • 1
    1. Loading a path from the bundle should not fail. It should be force-unwrapped. If it crashes then you know you made a mistake such as forgetting to target the file. No need for the `if let` getting the path. 2. Use `Bundle.main.url` to directly get a URL. – rmaddy May 26 '18 at 16:19