如果我设置了一个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
}发布于 2018-01-23 08:44:18
AVPlayerLayer保持对播放器的强烈引用,所以您不应该保留来自播放器本身的对playerLayer的强烈引用。
解决方案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管理器中创建强引用变量。
发布于 2018-01-23 08:42:31
在您的代码中,MyPlayer保持对playerLayer属性的引用。playerLayer属性保持对MyPlayer的引用。这就是保持循环。
作为解决方案,您不需要在player类中存储playerLayer属性。或者,您可以创建一些装饰类,它将同时管理播放器和他的层。
https://stackoverflow.com/questions/48395113
复制相似问题