URL to local Bundle.main always returns nil

Viewed 3817

Overview

I’m doing a simple singing game for kids. The game just plays a video and shows three options. I was updating the videos, so I deleted it from the Assets.xcassets then added the new ones.

The problem

Now I’m getting this error:

Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Volumes/Documentos/Trabajo/Codigo proyectos/Currents/HANDSUP/diloEnSenas/SingsCategoryView.swift, line 69
2020-05-12 14:03:46.769427-0500 HandsUP[12221:549710] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Volumes/Documentos/Trabajo/Codigo proyectos/Currents/HANDSUP/diloEnSenas/SingsCategoryView.swift, line 69

This is the code where I have the problem

struct video: View {
    var url: String

    var body: some View{
        VideoPlayerView(playerQueve: self.changeVideo(file: self.url))
    }

    func changeVideo(file: String) -> AVQueuePlayer {

        //let fileURL = file
        //let url = Bundle.main.url(forResource: fileURL , withExtension: "mp4")

        let url = Bundle.main.url(forResource: "color_1" , withExtension: "mp4")

        let playerItem = AVPlayerItem(url: url!)

        //set video

        let player = AVQueuePlayer(playerItem: playerItem)

        return player
    }
}

It was working fine before. So my first thought was that I’m not adding the files in the right way, but I checked it again and the buttons that are in the same folder as the videos are showing correctly.

enter image description here enter image description here enter image description here enter image description here

Like you can see in the last image the button is showing well and the button image is in the same folder

enter image description here

enter image description here Second thing I checked was the build phase but all files are in the right folder.

Question

  • Why isn't it getting the file?
  • How can I debug the URL?
4 Answers

Ok im still very confuse about what happens but here is what work for me

to start I was using an external disk an the source code was there so im pretty sure is not related but I change the location to my local disk.

First i delete all the files an also in finder I delete the real files on the folder on the project.

Second then I copy my assets folder whit finder in the project folder

enter image description here

Third I drag all the folder to the main bundle but instead of check create group I check create folder references

enter image description here

So that make all my folders yellow (when I drag the folder an check create group the inside folders turn blue)

Four I drag and drop the yellow folder to the Assets.xcassets (I have the images buttons for every video also on the folders)

and run all again so its working again

enter image description here

So now its working again thanks all for the help I think the key its to have the real files on the bundle and the target check.

If you want to get data from Assets.xcassets, you should use NSDataAsset like NSDataAsset(name: "color_1")?.data. You do however get the raw data rather than an URL. So in your implementation it is critical to copy the mp4 file in the Copy Bundle Resources build phase, which will copy it directly to your main app bundle as per Bundle Structures, rather than add it to the xcassets catalog. Make sure to use the same file name and extension for the file you copy as the one used in your code.

If you add your video files to your main bundle, by dragging and drop it and copy items if needed, you can access them directly like this:

let url = Bundle.main.url(forResource: "Test" , withExtension: "mov")

If you want to access your video directly from the Asset, you can get it as NSObject with NSDataAsset.

let dataVideo : NSObject = NSDataAsset(name: "MyVideo")!

Edit:

If you add your Video/ Images to your MainBundle, you can see them when showing package content of your app. That's where the URL is pointing to. With asset you do not get a URL by stock. What I am doing is, I get the content of the Asset as Data, copy that into the Documents folder of my application and store it there. Then you get a URL to that directory aswell. (This should be the optimal solution for your case, I would just copy the videos to your Bundle directly)

func changeVideo(file: String) -> AVQueuePlayer? {

   //let fileURL = file
   //let url = Bundle.main.url(forResource: fileURL , withExtension: "mp4")

    If let url = Bundle.main.url(forResource: "color_1" , withExtension: "mp4”) {

            let playerItem = AVPlayerItem(url: url)

            //set video

            let player = AVQueuePlayer(playerItem: playerItem)

            return player
    }
    else {
         return nil
    }
}

Wrap the url parameter and make the modifications to: VideoPlayerView(playerQueve: self.changeVideo(file: self.url))

Related