Home > Mobile >  SwiftUi how can I load selected video from item identifier
SwiftUi how can I load selected video from item identifier

Time:10-27

I am new to Swift and have been using the new PhotosPicker in SwiftUI 4.0 . I am able to display selected images but not video . When I select a video I can get a few pieces of information like this below

PhotosPickerItem(_itemIdentifier: Optional("40F724uF-24M7-4523-9B2B-AD43FB2C7D71/L0/001"), _shouldExposeItemIdentifier: false, _supportedContentTypes: [<_UTCoreType 0x106c4cd60> com.apple.quicktime-movie (not dynamic, declared)], _itemProvider: <PUPhotosFileProviderItemProvider: 0x600003ea05a0> {types = ( "com.apple.quicktime-movie" )})

I am wondering if there is somehow that I can use that item identifier to load the video selected . I am been looking at different examples but none of them show videos for PhotosPicker . I have a very small project that I am testing this on, any suggestions would be great

     import SwiftUI
     import Combine
     import PhotosUI
     import AVKit

    struct PlayVideoView: View {
    @State private var selectedItem: [PhotosPickerItem] = []
    @State private var data: Data?
    @State var player = AVPlayer(url: URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4")!)
    
    var body: some View {
        PhotosPicker(selection: $selectedItem,
                     maxSelectionCount: 1,
                     matching: .any(of: [.images,.videos])) {
            Image(systemName: "photo")
                .resizable()
                .foregroundColor(.blue)
                .frame(width: 24, height: 24)
                .padding(.top, 5.0)
        }.onChange(of: selectedItem) { newMedia in
            Task {
                guard let item = selectedItem.first else {
                    return
                }
                item.loadTransferable(type: Data.self) { result in
                    
                    switch result {
                    case .success(let data):
                        if let data = data {
                            print(item) // get video url here and display in videoplayer
                            self.data = data
                            
                        } else {
                            print("data is nil")
                        }
                    case .failure(let failure):
                        fatalError("\(failure)")
                    }
                }
            }
        }
        VideoPlayer(player: player) // selected video url should go here
             .frame(width: 400, height: 300, alignment: .center)
    }
}

struct PlayVideoView_Previews: PreviewProvider {
    static var previews: some View {
        PlayVideoView()
     }
    }

CodePudding user response:

You could try this approach, using the code from https://github.com/zunda-pixel/SamplePhotosPicker. The Movie code replicated here, uses the TransferRepresentation to represent a url from the temp file.

import Foundation
import SwiftUI
import PhotosUI
import AVKit
import CoreTransferable


// from: https://github.com/zunda-pixel/SamplePhotosPicker
struct Movie: Transferable {
  let url: URL

  static var transferRepresentation: some TransferRepresentation {
    FileRepresentation(contentType: .movie) { movie in
      SentTransferredFile(movie.url)
    } importing: { receivedData in
      let fileName = receivedData.file.lastPathComponent
      let copy: URL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName)

      if FileManager.default.fileExists(atPath: copy.path) {
        try FileManager.default.removeItem(at: copy)
      }

      try FileManager.default.copyItem(at: receivedData.file, to: copy)
      return .init(url: copy)
    }
  }
}

struct ContentView: View {
    var body: some View {
        PlayVideoView()
    }
}

struct PlayVideoView: View {
    @State private var selectedItem: [PhotosPickerItem] = []
    @State var player = AVPlayer(url: URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4")!)
    
    var body: some View {
        PhotosPicker(selection: $selectedItem,
                     maxSelectionCount: 1,
                     matching: .any(of: [.images,.videos])) {
            Image(systemName: "photo")
                .resizable()
                .foregroundColor(.blue)
                .frame(width: 24, height: 24)
                .padding(.top, 5.0)
        }.onChange(of: selectedItem) { newMedia in
            Task {
                guard let item = selectedItem.first else {  return }
                item.loadTransferable(type: Movie.self) { result in   // <-- here
                    switch result {
                    case .success(let movie):
                        if let movie = movie {
                            player = AVPlayer(url: movie.url) // <-- here
                        } else {
                            print("movie is nil")
                        }
                    case .failure(let failure):
                        fatalError("\(failure)")
                    }
                }
            }
        }
        VideoPlayer(player: player)
            .frame(width: 400, height: 300, alignment: .center)
    }
}
  • Related