ios - tvOS 应用内存问题 : How to resolve it?

标签 ios swift memory memory-management tvos

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

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

有什么方法可以解决内存问题并避免应用程序停止?

另一个问题是:在 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()
    }
}

}

最佳答案

我在您的代码中看到两个问题:

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

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

  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], 通知中

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

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

关于ios - tvOS 应用内存问题 : How to resolve it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42871131/

相关文章:

ios - 如何从 UIButton 操作方法获取 UITableViewCell 对象?

ios - 聚类谷歌地图标记并放大聚类

string-formatting - Double 的字符串格式

ios - 将文本字段导出集合添加在一起

xcode - 如何使用 SQlite Random()

ios - 查找当前事件的 View Controller

ios - 如何在 Swift 中展开/折叠 Collection View 部分?

c - 为 C 中的动态二维数组赋值时出现段错误

gcc - LDMIA 指令在皮质 M4 的外部 SRAM 上无法正常工作

Java Neo4J 内存不足