3

此处代码的想法是在视图 ( self.mv) 已被UIDynamicAnimator.

下面的代码基于Matt Neuburg编写的iOS 12 编程一书的第 4 章中的示例。作者说行为和视图(self.mv在代码中)都不会被释放。但他没有详细说明这一点。

我的问题是:

  1. 谁还保留着之后的行为self.anim.removeAllBehaviors()

  2. 谁还留着self.mv

我使用了 Instruments,但我不太了解输出。这是否意味着动画师保留了它?但是只有绿色的复选标记。

仪器屏幕截图

使用 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)

    }
}
4

2 回答 2

1

你有:

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.
        }
于 2019-02-05T21:56:26.453 回答
0

self 拥有 anim 拥有 grav 拥有保留 self 的动作块。

那是一个保留循环,所以 self 的引用计数永远不会减为零,所以 self 会泄漏。

你需要跳弱者舞来解决这个问题。

{[weak self] in
  if let strongSelf = self {
    let items = strongSelf.anim.views(in: strongSelf.view.bounds)
    ...
于 2019-02-02T16:17:43.930 回答