【问题标题】:AVPlayerViewController not deallocating immediatelyAVPlayerViewController 不会立即解除分配
【发布时间】:2015-11-26 21:26:08
【问题描述】:

我正在 TVos 的应用中播放视频。我正在使用 AVPlayerViewController 播放视频。但是,当我按下 Apple Tv 遥控器上的菜单按钮时,我会回到我来到这里的视图控制器,但视频继续播放,并且在 8 或 10 秒后它被释放。这真的是一个糟糕的错误,我被困了几天。任何帮助将不胜感激。

这是我的视图控制器代码。

import Foundation
import UIKit
import AVKit


class ViewController : UIViewController {


    var avplayerVC : AVPlayerViewController?
    var recentlyWatchedTimer : NSTimer?
    var lessonToWatch : Lesson?


    override func viewDidLoad() {
        super.viewDidLoad()


        if let urlVideo = lessonToWatch?.lessonurl {

            let activityIndicator = UIActivityIndicatorView(frame: CGRectMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0, 30.0, 30.0))
            let asset : AVURLAsset = AVURLAsset(URL: NSURL.init(string: urlVideo)!, options: nil)
            let keys = ["playable"];
            avplayerVC = AVPlayerViewController()

            weak var weakSelf = self

            asset.loadValuesAsynchronouslyForKeys(keys) { () -> Void in
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    weakSelf!.avplayerVC?.player =  AVPlayer(playerItem: AVPlayerItem(asset: asset))
                    weakSelf!.avplayerVC?.player?.seekToTime(kCMTimeZero)


                    print("Status 1: " +  "\(self.avplayerVC?.player?.status.rawValue)")
                    print(self.view?.frame)
                    // doesn't work

                    weakSelf!.avplayerVC?.view.frame =  self.view.frame
                    activityIndicator.stopAnimating()
                    activityIndicator.removeFromSuperview()
                    weakSelf!.view.addSubview((self.avplayerVC?.view!)!)
                    weakSelf!.avplayerVC?.player?.play()
                    weakSelf!.recentlyWatchedTimer = NSTimer.scheduledTimerWithTimeInterval(20.0, target: self, selector: "addToRecentlyWatched" , userInfo: nil, repeats: false)
                                    })
            }

            print("In LessonPlayViewController View Did Load")
            self.view.addSubview(activityIndicator)
            activityIndicator.startAnimating()
        }

    }


    func addToRecentlyWatched() {
        if let lesson = lessonToWatch {
            DataManager.sharedInstance.addRecentlyWatch(lesson)
        }
        recentlyWatchedTimer?.invalidate()
    }

    deinit {
        print("deinit")
        avplayerVC?.view.removeFromSuperview()
        avplayerVC?.player = nil
        avplayerVC = nil
    }

    // MARK : AVPlayerViewControllerDelegate


}

【问题讨论】:

    标签: ios swift avplayer tvos avplayerviewcontroller


    【解决方案1】:

    您想在异步回调块内的所有位置使用weakSelf,但您正在一次打印self.view.frame。

    【讨论】:

    • 嗯,这没有任何区别。在异步块中将所有自我更改为弱自我
    • @Madu deinit 被调用时的堆栈跟踪是什么。它是哪个线程?
    【解决方案2】:

    您应该使用捕获列表来确保对 self 的所有引用在闭包内都是 weak。然后使用guard 检查引用在闭包中是否仍然有效。

    import Foundation
    import UIKit
    import AVKit
    import AVFoundation
    
    
    class ViewController : UIViewController {
    
    
        var avplayerVC : AVPlayerViewController?
        var recentlyWatchedTimer : NSTimer?
        var lessonToWatch : Lesson?
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
            if let urlVideo = lessonToWatch?.lessonurl {
    
                let activityIndicator = UIActivityIndicatorView(frame: CGRectMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0, 30.0, 30.0))
                let asset : AVURLAsset = AVURLAsset(URL: NSURL.init(string: urlVideo)!, options: nil)
                let keys = ["playable"];
                avplayerVC = AVPlayerViewController()
    
                asset.loadValuesAsynchronouslyForKeys(keys) { [weak self] in
                    dispatch_async(dispatch_get_main_queue()) { [weak self] in
                        guard let vc = self, playerVC = vc.avplayerVC else {
                            return
                        }
    
                        playerVC.player = AVPlayer(playerItem: AVPlayerItem(asset: asset))
                        playerVC.player?.seekToTime(kCMTimeZero)
    
    
                        print("Status 1: " +  "\(playerVC.player?.status.rawValue)")
                        print(vc.view?.frame)
                        // doesn't work
    
                        playerVC.view.frame = vc.view.frame
                        activityIndicator.stopAnimating()
                        activityIndicator.removeFromSuperview()
                        vc.view.addSubview(playerVC.view)
                        playerVC.player?.play()
                        vc.recentlyWatchedTimer = NSTimer.scheduledTimerWithTimeInterval(20.0, target: vc, selector: "addToRecentlyWatched" , userInfo: nil, repeats: false)
                    }
                }
    
                print("In LessonPlayViewController View Did Load")
                self.view.addSubview(activityIndicator)
                activityIndicator.startAnimating()
            }
    
        }
    
    
        func addToRecentlyWatched() {
            if let lesson = lessonToWatch {
                DataManager.sharedInstance.addRecentlyWatch(lesson)
            }
            recentlyWatchedTimer?.invalidate()
        }
    
        deinit {
            print("deinit")
            avplayerVC?.view.removeFromSuperview()
            avplayerVC?.player = nil
            avplayerVC = nil
        }
    
        // MARK : AVPlayerViewControllerDelegate
    
    
    }
    

    更多关于捕获列表: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID57

    编辑

    另请注意,您应该在离开视图控制器时明确停止视频播放,而不是依赖播放器停止播放作为其释放的一部分。 IE。在viewDidDisappear 或类似的地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      • 1970-01-01
      相关资源
      最近更新 更多