创建 AVPlayerLayer 会阻止释放 AVPlayer
Creating AVPlayerLayer prevents releasing AVPlayer
如果我曾经设置过 AVPlayerLayer,那么就会有一些保留周期会阻止 deinit
被调用。
import AVFoundation
class MyPlayer: AVPlayer {
fileprivate(set) lazy var playerLayer: AVPlayerLayer = {
// Create a player layer
[=10=].videoGravity = AVLayerVideoGravityResizeAspectFill
[=10=].backgroundColor = UIColor.black.cgColor
return [=10=]
}(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
}
在您的代码 MyPlayer
中保持对 playerLayer
属性 的引用。而playerLayer
属性 保持对MyPlayer
的引用。这就是保留周期。
作为解决方案,您无需在播放器 class 中存储 playerLayer
属性。或者你可以创建一些装饰器 class 来管理玩家和他的图层
AVPlayerLayer
保持对播放器的强引用,所以你不应该保持对播放器本身的 playerLayer 的强引用。
解决方案 1
如果你不打算移除sublayer,那么superlayer会为你保留reference,所以你可以使用weak
:
private weak var _playerLayer: AVPlayerLayer?
var playerLayer: AVPlayerLayer! {
if let p = _playerLayer {
return p
}
let p: AVPlayerLayer = {
// Create a player layer
[=10=].videoGravity = AVLayerVideoGravityResizeAspectFill
[=10=].backgroundColor = UIColor.black.cgColor
return [=10=]
}(AVPlayerLayer(player: self))
_playerLayer = p
return p
}
解决方案 2
如果您打算删除并重新添加子图层,那么您需要在 UIView、UIViewController 或播放器图层的其他管理器中创建强引用变量。
如果我曾经设置过 AVPlayerLayer,那么就会有一些保留周期会阻止 deinit
被调用。
import AVFoundation
class MyPlayer: AVPlayer {
fileprivate(set) lazy var playerLayer: AVPlayerLayer = {
// Create a player layer
[=10=].videoGravity = AVLayerVideoGravityResizeAspectFill
[=10=].backgroundColor = UIColor.black.cgColor
return [=10=]
}(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
}
在您的代码 MyPlayer
中保持对 playerLayer
属性 的引用。而playerLayer
属性 保持对MyPlayer
的引用。这就是保留周期。
作为解决方案,您无需在播放器 class 中存储 playerLayer
属性。或者你可以创建一些装饰器 class 来管理玩家和他的图层
AVPlayerLayer
保持对播放器的强引用,所以你不应该保持对播放器本身的 playerLayer 的强引用。
解决方案 1
如果你不打算移除sublayer,那么superlayer会为你保留reference,所以你可以使用weak
:
private weak var _playerLayer: AVPlayerLayer?
var playerLayer: AVPlayerLayer! {
if let p = _playerLayer {
return p
}
let p: AVPlayerLayer = {
// Create a player layer
[=10=].videoGravity = AVLayerVideoGravityResizeAspectFill
[=10=].backgroundColor = UIColor.black.cgColor
return [=10=]
}(AVPlayerLayer(player: self))
_playerLayer = p
return p
}
解决方案 2
如果您打算删除并重新添加子图层,那么您需要在 UIView、UIViewController 或播放器图层的其他管理器中创建强引用变量。