此处的代码的想法是,当视图self.mv
在屏幕上被UIDynamicAnimator
动画化时,将其删除。
下面的代码基于Matt Neuburg撰写的《 Programming iOS 12 》第4章中的示例。作者说,行为和视图(代码中的self.mv
)都不会被取消分配。但是他没有对此进行详尽的阐述。
我的问题是:
在self.anim.removeAllBehaviors()
之后谁仍然保留该行为?
谁仍然保留self.mv
?
我使用了乐器,但是我不太理解输出。这是否意味着动画师保留了它?但是只有绿色的复选标记。
使用XCode中的“调试内存图”工具,即使调用UIGravityBehavior
之后,动画师仍会保留self.anim.removeAllBehaviors()
。
class MyView : UIView {
deinit {
print("dddddddd")
}
}
class ViewController: UIViewController {
var anim : UIDynamicAnimator!
weak var mv : MyView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let v = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
v.backgroundColor = .red
self.view.addSubview(v)
self.mv = v
let grav = UIGravityBehavior()
self.anim = UIDynamicAnimator(referenceView: self.view)
self.anim.addBehavior(grav)
grav.action = {
let items = self.anim.views(in: self.view.bounds)
let idx = items.firstIndex(of: self.mv!)
if idx == nil {
self.anim.removeAllBehaviors()
self.mv!.removeFromSuperview()
// self.anim = nil // without this, the `MyView` is not deallocated.
}
}
grav.addItem(v)
}
}
答案 0 :(得分:2)
您有:
var anim : UIDynamicAnimator!
如果成功的话:
var anim : UIDynamicAnimator?
,并在动画制作完成后在回调中nil
if idx == nil {
self.anim?.removeAllBehaviors()
self.mv!.removeFromSuperview()
self.anim = nil // without this, the `MyView` is not deallocated.
}
,这样可以解决您的额外保留问题:
entry
答案 1 :(得分:0)
self拥有拥有重力的动画,而grav拥有保留自我的动作块。
这是一个保留循环,所以自的引用计数将永远不会被递减到零,所以自会泄漏。
您需要做弱者舞蹈来解决此问题。
{[weak self] in
if let strongSelf = self {
let items = strongSelf.anim.views(in: strongSelf.view.bounds)
...