swifturlswiftuiavplayeritem

URL to local Bundle.main always returns nil


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


Solution

  • 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)