我有一个 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()
}
}
}
最佳答案
我在您的代码中看到两个问题:
- 每次调用
playVideoWithURL
方法时,您都会创建新的AVPlayer
实例,而不是重复使用已经存在的实例。您可以调用replaceCurrentItem(with:)当你想播放另一个 URL 时,你的player
属性上的方法。
这本身有点低效,但不应导致您描述的内存问题。我认为原因是:
- 每次调用
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/