创建AVPlayerLayer会阻止释放AVPlayer

时间:2018-01-23 05:56:20

标签: ios swift avplayer retain-cycle avplayerlayer

如果我设置了AVPlayerLayer,那么会有一些保留周期阻止deinit被调用。

import AVFoundation

class MyPlayer: AVPlayer {

    fileprivate(set) lazy var playerLayer: AVPlayerLayer = {
        // Create a player layer
        $0.videoGravity = AVLayerVideoGravityResizeAspectFill
        $0.backgroundColor = UIColor.black.cgColor
        return $0
    }(AVPlayerLayer(player: self))

    override init() {
        super.init()
        print("MyPlayer init")

        _ = playerLayer
    }

    deinit {
        print("MyPlayer deinit")
    }
}

使用此测试,只会打印" MyPlayer init"

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    _ = MyPlayer()

    return true
}

2 个答案:

答案 0 :(得分:1)

在代码MyPlayer中,请继续引用playerLayer属性。 playerLayer属性会引用MyPlayer。这使得保留周期。

作为解决方案,您不需要在您的播放器类中存储playerLayer属性。或者你可以创建一些装饰类,它们将管理玩家和他的图层

答案 1 :(得分:1)

AVPlayerLayer保持对玩家的强烈引用,因此你不应该保持玩家本身对玩家层的强烈引用。

解决方案1 ​​

如果您不打算删除子图层,那么超级图层会为您保留参考,因此您可以使用weak

private weak var _playerLayer: AVPlayerLayer?
var playerLayer: AVPlayerLayer! {
    if let p = _playerLayer {
        return p
    }
    let p: AVPlayerLayer = {
        // Create a player layer
        $0.videoGravity = AVLayerVideoGravityResizeAspectFill
        $0.backgroundColor = UIColor.black.cgColor
        return $0
    }(AVPlayerLayer(player: self))
    _playerLayer = p
    return p
}

解决方案2

如果您打算删除并重新添加子图层,那么您需要在UIView,UIViewController或其他管理器中为playerLayer创建强引用变量。