swiftui deallo c и reallo c AVplayer со многими видео - PullRequest
0 голосов
/ 07 апреля 2020

У меня много одновременных видео. Через Int var (var test1 и var test2) я хотел бы иметь возможность добавить только определенное видео и удалить все остальные, чтобы не было проблем с памятью

Как только загрузится представление, Значение «nil» присваивается каждому игроку, и когда test1 == test 2, он должен загрузить видео в определенный плеер, а в другой «nil»

Проблема в том, что, несмотря на то, что она является тестовой переменной в связывании ( struct VideoPlayer @ Binding var testing) не обновляет состояние плеера, который всегда остается в Nil

Ниже лучшего решения, которое я получил до сих пор

Есть идеи? Спасибо всем

struct CustomPlayer: View {
    @Binding var test1:Int
    @Binding var test2:Int
    @State var path:String

    @State var testing:AVPlayer? = nil

    var body: some View {
            if(test1 == test2 ) {
                    self.testing? = AVPlayer(url: URL(fileURLWithPath:  Bundle.main.path(forResource: "\(path)", ofType: "mp4")!)  )
                    self.testing?.play()
            } else {
                    self.testing?.replaceCurrentItem(with: nil)
            }
             return ZStack{
                VideoPlayer(testing: self.$testing)

            }




struct VideoPlayer : UIViewControllerRepresentable {

    @Binding var testing : AVPlayer?


    func makeUIViewController(context: UIViewControllerRepresentableContext<VideoPlayer>) -> AVPlayerViewController {

        let controller = AVPlayerViewController()

        controller.player = testing
        controller.showsPlaybackControls = false
        controller.view.backgroundColor = UIColor.white
        return controller

    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayer>) {


    }
}

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Вот пример того, как загрузить несколько видео одновременно (я добавил функцию автозапуска) и удалить все остальные, кроме выбранного. Чтобы удалить видео, нажмите на видео, которое вы хотите сохранить

И я не уверен, что я решу вашу первоначальную проблему, но это может дать вам подсказку, где искать дальше

Код можно скопировать / вставил, как я объявляю это в одном файле для удобного использования stackoverflow

  import SwiftUI
  import AVKit

  struct VideoModel: Identifiable {
    let id: Int
    let name: String
    let type: String = ".mp4"
  }

  final class VideoData: ObservableObject {
    @Published var videos = [VideoModel(id: 100, name: "video"),
                             VideoModel(id: 101, name: "wow"),
                             VideoModel(id: 102, name: "okay")]
  }


  //Multiple item player
  struct MultipleVideoPlayer: View {
    @EnvironmentObject var userData: VideoData

    var body: some View {
      VStack(alignment: .center, spacing: 8) {
        ForEach(userData.videos) { video in
          VideoPlayer(video: .constant(video))
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 250, maxHeight: 250, alignment: .center)
        }
      }
    }
  }

  //Single item player
  struct VideoPlayer : UIViewControllerRepresentable {
    @EnvironmentObject var userData: VideoData
    @Binding var video: VideoModel

    func makeUIViewController(context: Context) -> AVPlayerViewController {
      guard let path = Bundle.main.path(forResource: video.name, ofType: video.type) else {
        fatalError("\(video.name)\(video.type) not found")
      }
      let url = URL(fileURLWithPath: path)
      let playerItem = AVPlayerItem(url: url)

      context.coordinator.player = AVPlayer(playerItem: playerItem)
      context.coordinator.player?.isMuted = true
      context.coordinator.player?.actionAtItemEnd = .none

      NotificationCenter.default.addObserver(context.coordinator,
                                             selector: #selector(Coordinator.playerItemDidReachEnd(notification:)),
                                             name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                             object: context.coordinator.player?.currentItem)

      let controller = AVPlayerViewController()
      controller.player = context.coordinator.player
      controller.showsPlaybackControls = false
      controller.view.backgroundColor = UIColor.white

      controller.delegate = context.coordinator

      let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.playerDidTap))
      controller.view.addGestureRecognizer(tapRecognizer)
      return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
      uiViewController.player?.play()
    }

    func makeCoordinator() -> Coordinator {
      let coord = Coordinator(self)
      return coord
    }


    class Coordinator: NSObject, AVPlayerViewControllerDelegate {
      var parent: VideoPlayer
      var player: AVPlayer?

      init(_ playerViewController: VideoPlayer) {
        self.parent = playerViewController
      }

      @objc func playerItemDidReachEnd(notification: NSNotification) {
        if let playerItem: AVPlayerItem = notification.object as? AVPlayerItem {
          playerItem.seek(to: CMTime.zero, completionHandler: nil)
        }
      }


      @objc func playerDidTap(){
        parent.userData.videos = parent.userData.videos.filter { videoItem in
          return videoItem.id == parent.video.id
        }
      }

    }
  }



  //preview
  struct AnotherEntry_Previews: PreviewProvider {
    static var previews: some View {
      MultipleVideoPlayer()
    }
  }

А в 'SceneDelegate.swift' замените точку входа приложения на

  window.rootViewController = UIHostingController(rootView: MultipleVideoPlayer().environmentObject(VideoData()))

Ключевая вещь этого шага чтобы иметь ресурс «VideoData», вы можете достичь его с помощью EnvironmentObject или с помощью другого примера с общими данными

Видео ниже, я добавил в проект, включая их в Target Membership of project

enter image description here

@Published var videos = [VideoModel(id: 100, name: "video"),
                         VideoModel(id: 101, name: "wow"),
                         VideoModel(id: 102, name: "okay")]
0 голосов
/ 08 апреля 2020

Ваш код, кажется, в порядке. Вы уверены, что путь AVPlayer (...) правильный и тестирование не равно нулю. Поместите

.....
self.testing?.play()
print("-----> testing: \(testing.debugDescription)")

, тестирует = ноль в этот момент?

...