【问题标题】:tvOS app memory issue: How to resolve it?tvOS 应用程序内存问题:如何解决?
【发布时间】:2017-08-09 19:32:56
【问题描述】:

我有一个 tvOS 应用程序,其中播放视频。 基本上有两个视频(同一视频的不同速度版本)。一个是 12MB,另一个是 1.9MB。

当应用启动时,它运行良好(Xcode 显示 191MB)。但是,当单击一次正常速度按钮时,内存会增加到 350MB。当我分别单击正常和快速按钮时,它会继续增加,并在某一时刻变成 1GB+。你可以看到附件。当视频卡顿和应用停止时,它甚至达到了 3GB。

有什么办法可以解决内存问题,避免应用停止?

另一个问题是:在 Apple TV 中,当我们从这个应用程序转到另一个应用程序并返回时,视频再次停止。但是,在模拟器中,它没有发生。有人可以帮我解决这两个问题吗?

这是我正在使用的代码:

var avPlayerLayer: AVPlayerLayer!
var paused: Bool = false

func playmyVideo(myString: String) {

    let bundle: Bundle = Bundle.main
    let videoPlayer: String = bundle.path(forResource: myString, ofType: "mov")!
    let movieUrl : NSURL = NSURL.fileURL(withPath: videoPlayer) as NSURL

    print(movieUrl)

    viewVideo.playVideoWithURL(url: movieUrl)


}
@IBAction func normalPressed(_ sender: Any) {

    playmyVideo(myString: "normal")


}


@IBAction func forwardPressed(_ sender: Any) {

    playmyVideo(myString: "fast")

}

class VideoPlay: UIView {


private var player : AVPlayer!

private var playerLayer : AVPlayerLayer!

init() {

    super.init(frame: CGRect.zero)
    self.initializePlayerLayer()

}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.initializePlayerLayer()
    self.autoresizesSubviews = false
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.initializePlayerLayer()

}



private func initializePlayerLayer() {

    playerLayer = AVPlayerLayer()
    playerLayer.backgroundColor = UIColor.clear.cgColor



    playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill


    self.layer.addSublayer(playerLayer)

    playerLayer.frame = UIScreen.main.bounds


}

func playVideoWithURL(url: NSURL) {

    player = AVPlayer(url: url as URL)
    player.isMuted = false

    playerLayer.player = player

    player.play()

    loopVideo(videoPlayer: player)
}

func toggleMute() {
    player.isMuted = !player.isMuted
}

func isMuted() -> Bool
{
    return player.isMuted
}

func loopVideo(videoPlayer: AVPlayer) {

    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in
        let t1 = CMTimeMake(5, 100);
        self.player.seek(to: t1)
        videoPlayer.seek(to: kCMTimeZero)
        self.player.play()
    }
}

}

【问题讨论】:

  • 还有一些代码你在用什么?
  • @SamuelTulach 嗨。我已经包含了我们正在使用的代码
  • @SamuelTulach 嗨。请我们审查我的代码...

标签: ios swift memory memory-management tvos


【解决方案1】:

我在您的代码中发现了两个问题:

  1. 每次调用playVideoWithURL 方法时,您都会创建新的AVPlayer 实例,而不是重用已经存在的实例。当您想播放另一个 URL 时,可以在 player 属性上调用 replaceCurrentItem(with:) 方法。

这本身效率有点低,但不应导致您描述的内存问题。我认为原因是:

  1. 每次调用loopVideo 方法时,都会将闭包传递给NotificationCenter.default.addObserver。此闭包创建对videoPlayer 的强引用。您永远不会从通知中心删除观察者。

由于每次创建新的 AVPlayer 实例时都会调用 loopVideo,因此这些实例永远不会被释放,从而导致您描述的内存问题。

要修复它,您可以:

  • playVideoWithURL 中只初始化一次player 属性,然后在您想播放另一个视频时使用replaceCurrentItem
  • 还要更改“循环”逻辑,以便您只调用一次NotificationCenter.default.addObserver
  • 您传递给NotificationCenter.default.addObserver 的闭包会造成内存泄漏(请参阅this question)。你可以通过弱捕获self来摆脱它:

    NotificationCenter.default.addObserver(forName:
    NSNotification.Name.AVPlayerItemDidPlayToEndTime,object: nil, queue: nil) { [weak self], notification in

      self?.player.seek(to: kCMTimeZero)
      self?.player.play()
    

    }

还记得在VideoPlay类的deinit方法中调用removeObserver

【讨论】:

    猜你喜欢
    • 2012-11-29
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    相关资源
    最近更新 更多