'The video from the core data is not displayed

in swift UIKit

Via PHPickerViewController

Choose the video and store it in the core data successfully

result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, err in
            do {
                if let urls = url {
                    
                    let localURL = FileManager.default.temporaryDirectory.appendingPathComponent(urls.lastPathComponent)
                    try? FileManager.default.removeItem(at: localURL)
                    try FileManager.default.copyItem(at: urls, to: localURL)
                    DispatchQueue.main.sync {

                        coreDateHelperMedia().storeMedia(urlImg: UIImage.init(), videoURL: urls, types: "video")
                        self.collection.reloadData()
                    }
                }
            } catch let error {
                print("Error",error)
            }
        }

This is the url

- _url : file:///Users/badrshammry/Library/Developer/CoreSimulator/Devices/7986A27F-7026-45E1-9073-78CCD6A9B90A/data/Containers/Data/Application/E0C76BFB-16C0-4C65-A80C-9D931FFC1EB9/tmp/8bbab7eb-1530-46b2-8bfa-6e9d9262354e.mp4

And when you press it in cell in didSelectItemAt This url comes from the core data

- _url : file:///Users/badrshammry/Library/Developer/CoreSimulator/Devices/7986A27F-7026-45E1-9073-78CCD6A9B90A/data/Containers/Data/Application/E0C76BFB-16C0-4C65-A80C-9D931FFC1EB9/tmp/.com.apple.Foundation.NSItemProvider.ZUVWZt/8bbab7eb-1530-46b2-8bfa-6e9d9262354e.mp4

Here I am playing the video

let dataUrl = arrS1[indexPath.row]
        let urlvideo = dataUrl.videoSection?.absoluteString

guard let url = URL(string: urlvideo!) else {return}
            let player = AVPlayer(url: URL(fileURLWithPath:url.path))
            playerController = AVPlayerViewController()
            playerController.player = player
            playerController.allowsPictureInPicturePlayback = true
            playerController.delegate = self
            present(playerController, animated: true) {
                player.play()
            }

The problem is that it is stuck in the process of running

enter image description here

enter image description here

the coreDateHelperMedia()

//MARK: - Store
func storeMedia (urlImg : UIImage , videoURL : URL , types : String){
    
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
    let entity = NSEntityDescription.entity(forEntityName: "MediaEntity", in: context)
    let coreDataObject = NoteEntity(entity: entity!, insertInto: context)
    coreDataObject.setValue(urlImg, forKey: "img")
    coreDataObject.setValue(videoURL, forKey: "video")
    coreDataObject.setValue(types, forKey: "typeString")
    coreDataObject.setValue(UUID(), forKey: "id")
    do {
        try context.save()

    } catch let error {
        print(error.localizedDescription)
    }
}
//MARK: - Fetch

func fetchMedia ()->[MediaModel]{

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
        return []
    }
    let managedContext = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "MediaEntity")
    var items : [MediaModel] = []
    do {
        items.removeAll()
        let coreDataObjects = try managedContext.fetch(fetchRequest)
        for item in coreDataObjects {

            var textItem = MediaModel.init()

            let image = item.value(forKey: "img")
            let video = item.value(forKey: "video")
            let type = item.value(forKey: "typeString")
            let uid = item.value(forKey: "id")

            if let vid = video ,let img = image , let udidd = uid {
                textItem.img = img as! UIImage
                textItem.video = vid as! URL
                textItem.typeString = type as! String
                textItem.id = udidd as! UUID

                items.append(textItem)
            }
        }
        return items
    } catch let error as NSError {
        print(error)
    }
    return []
}


Solution 1:[1]

A video is a bunch of Data or in practise a file in the file system. You aren't storing any video to your database. You are storing a URL that references a file in a temporary directory which you actively did by choosing FileManager.default.temporaryDirectory. That directory is temporary and doesn't survive long.

What you need to do is:

  1. Copy the video to your apps document directory where it will remain persistent over multiple app launches.
  2. Store a reference to the video as a relative URL. Store the name of the video in core data and rebuild the entire URL each time you want it.

You can always locate the app document directory via NSSearchPathForDirectoriesInDomains e.g:

enum AppURLS {
  static func documentsDirectory() -> URL {
    guard let docspath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last else {
      fatalError("unable to get system docs directory - serious problems")
    }
    return URL(fileURLWithPath: docspath)
  }
}

And your storage function will look like this:

func storeMedia (videoURL : URL) {
    let name = videoURL.lastPathComponent 
    let note = NoteEntity(etc)
    note.video = name //only store name
    
    let target = AppURLS.documentsDirectory().appendingPathComponent(name)
    try FileManager.default.copyItem(at: videoURL, to: target)
}

When you want the video back again use the name stored in the video property to rebuild the source URL and give that to your video player.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1