【问题标题】:swiftui dealloc and realloc AVplayer with many videosswiftui dealloc 和 realloc AVplayer 有很多视频
【发布时间】:2020-04-07 16:10:01
【问题描述】:

我有很多同步视频。通过 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>) {


    }
}

【问题讨论】:

    标签: swift uikit swiftui avplayer


    【解决方案1】:

    这是一个如何同时加载多个视频的示例(我添加了一个自动播放功能),并删除所有其他视频,但不删除所选视频。 要删除视频,请点按您要保存的视频

    我不确定我是否能解决您最初的问题,但这可以为您提供下一步寻找方向的线索

    代码可以复制/粘贴,因为我在一个文件中声明它以方便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,或者其他一些共享数据的例子来实现

    我添加到项目中的以下视频,包括项目的目标成员

    @Published var videos = [VideoModel(id: 100, name: "video"),
                             VideoModel(id: 101, name: "wow"),
                             VideoModel(id: 102, name: "okay")]
    

    【讨论】:

      【解决方案2】:

      您的代码似乎没问题。你确定 AVPlayer(...) 路径是正确的 并且测试不是零。放

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

      那时 testing = nil 吗?

      【讨论】:

      • 是...调试描述返回零。我尝试在 if(test1 == test2 ) { 之前添加 DispatchQueue.main.async { 但结果是一样的。谢谢!
      • 如果此时测试为零,那是因为 AVPlayer(url:..) 无法找到具有给定 url 的资源。您需要先解决此问题,然后其余代码(可能)才能工作。
      猜你喜欢
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多