Почему происходит цикл утечки / сохранения памяти после вызова закрытия UIDynamicBehavior? - PullRequest
0 голосов
/ 02 февраля 2019

Идея кода здесь состоит в том, чтобы удалить представление (self.mv), когда оно было анимировано вне экрана с помощью UIDynamicAnimator.

Код ниже основан на примерах из главы 4Книга Программирование iOS 12 от Мэтта Нойбурга.Автор говорит, что и поведение, и представление (self.mv в коде) не будут отменены.Но он не стал подробно останавливаться на этом.

Мои вопросы:

  1. Кто все еще сохраняет поведение после self.anim.removeAllBehaviors()?

  2. Кто все еще сохраняет self.mv?

Я использовал инструменты, но я не совсем понимаю вывод.Значит ли это, что аниматор его сохраняет?Но есть только зеленые галочки.

Instruments screen shot

С помощью инструмента «Debug Memory Graph» в XCode я увидел, что UIGravityBehavior все еще сохраняется аниматоромдаже после вызова self.anim.removeAllBehaviors().

Debug Memory Graph

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)

    }
}

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

У вас есть:

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.
        }
0 голосов
/ 02 февраля 2019

self владеет анимом, которому принадлежит грав, который владеет блоком действий, который сохраняет self.

Это цикл сохранения, поэтому счетчик ссылок self никогда не будет уменьшен до нуля, поэтому self будет просачиваться.

Вам нужно потанцевать, чтобы это исправить.

{[weak self] in
  if let strongSelf = self {
    let items = strongSelf.anim.views(in: strongSelf.view.bounds)
    ...
...