简体   繁体   中英

xcode9 swift4 Fatal error: Unexpectedly found nil while unwrapping an Optional value

I am trying to play a mp3 file(5 seconds) when app launched and I keep getting the error:

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

import UIKit
import AudioToolbox

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    //create SystemSoundID
    var soundID:SystemSoundID = 0
    let path = Bundle.main.path(forResource: "iPhone100Voice", ofType: "mp3")
    let baseURL = NSURL(fileURLWithPath: path!)
    AudioServicesCreateSystemSoundID(baseURL, &soundID)
    //play
    AudioServicesPlaySystemSound(soundID)

    }

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }

}

Can anyone explain why and how I can fix this?

Check these points, all conditions must be true:

  • Is the file in the project navigator?
  • Is the Target Membership checkbox checked in the File Inspector (to get it select the file and press ⌥⌘1 )
  • Is the file name spelled correctly ( iPhone100Voice.mp3 )?

Please check your file name, maybe filename is incorrect or not in the bundle

So please check file name with extension.

Use if let or guard to unwrap the path:

override func viewDidLoad() {

    super.viewDidLoad()
    var soundID:SystemSoundID = 0

    if let path = Bundle.main.path(forResource: "iPhone100Voice", ofType: "mp3") {
       let baseURL = NSURL(fileURLWithPath: path)
       AudioServicesCreateSystemSoundID(baseURL, &soundID)
       AudioServicesPlaySystemSound(soundID)
    } else {
        let alert = UIAlertController(title: "Alert", message: "File not found in your bundle", preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil))
        self.present(alert, animated: true, completion: nil)

   }
}

It may be help's to you to play video. While adding video file into project make sure target checkbox selected or not in file inspector.

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)


        if  let path = Bundle.main.path(forResource: "video_1523966087401 (1)", ofType: ".mp4"){
            let player = AVPlayer(url: URL(fileURLWithPath: path))
            let playerController = AVPlayerViewController()
            playerController.player = player
            present(playerController, animated: true) {
                player.play()
            }
        }else{
            //show dialog to user

            print("Error: File not found")
        }
    }

! means crash operator, it unwraps optional value. Value there works as like Optional(53) , for say. So the variable should contain value except nil, when path! tries to unwrap optional and appends value 53 in path variable.

to fix this we can use two ways

Using guard,

guard let pathValue = path else {
        return
}

let baseURL = NSURL(fileURLWithPath: pathValue) //no need to use pathValue, if you use then you have to use path!, although it makes no crash now.  
AudioServicesCreateSystemSoundID(baseURL, &soundID)
//play
AudioServicesPlaySystemSound(soundID)

if path is nil, it enters the block and return , if it has value , it continues to next line.

using if-let, knowing optional binding

if let pathValue = path {
    let baseURL = NSURL(fileURLWithPath: pathValue) //same comment
    AudioServicesCreateSystemSoundID(baseURL, &soundID)
    //play
    AudioServicesPlaySystemSound(soundID)
} 

Now, if path is optional , can't reach the block and pass to next line

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM