Подтвердить что ты не робот

Нужно ли использовать [unowned self] в закрытии UIView.animateWithDuration(...)?

    UIView.animateWithDuration(1,
        animations: { [unowned self] in
            self.box.center = self.boxTopRightPosition
        },
        completion: { [unowned self] completed in
            self.box.hidden = true
    })

Необходимо ли избегать утечки памяти?

4b9b3361

Ответ 1

Нет, в этом случае он не нужен. animations и completion не сохраняются на self, поэтому нет риска сильного цикла удержания.

Ответ 2

Ну, "необходимо" - это не то же самое, что "рекомендуется". Если ваш вопрос, если это необходимо, то ответ @Kirsteins в порядке, однако представьте себе ситуацию, когда вы хотите что-то оживить в своем контроллере просмотра после некоторой работы, но ваш контроллер просмотра был выпущен (потому что он больше не находится в иерархии представлений или по любой другой причине). В этом случае, если вы не используете [weak self], ваш контроллер просмотра не будет выпущен до окончания анимации, потому что вы сохраняете его в блоке анимации, но имеет смысл сохранить его, пока он не оживит что-то, что не в представлении больше?

Итак, в нескольких словах вам не нужно использовать ссылку weak для самостоятельной работы при анимации UIKit, однако вам не нужно сохранять свой вид сохраненным, если он будет выпущен, потому что анимация без представления не имеют смысл, поэтому использование weak является хорошим вариантом.

Ответ 3

@Plabo, как сказал Кирстейнс, анимации и завершение не сохраняются самим собой, поэтому даже если вы запустите анимацию и по какой-либо причине ваш контроллер просмотра будет выпущен, он будет освобожден мгновенно. Таким образом, вам не требуется захваченное "я". Рассмотрим глупый пример:

class ViewController: UIViewController {

    @IBOutlet weak var button : UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        print("viewDidLoad ViewController")
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        UIView.animate(withDuration: 20, animations: {
            self.button.frame = CGRect(x: 0, y: 300, width: 30, height: 30)
        }) { finished in
            self.button.frame = CGRect(x: 0, y: 100, width: 30, height: 30)
        }
    }

    deinit {
        print("deinit ViewController")
    }

}

Как только он будет освобожден, деинициализатор будет вызван, и завершение никогда не будет выполнено.

Ответ 4

Нет, это не нужно. Как говорит Кирстейнс:

Нет, это не нужно в этом случае. анимация и завершение не сохраняются самим собой, поэтому нет риска сильного цикла сохранения.

Но Имграсси говорит:

Как только он будет освобожден, будет вызван деинициализатор, и завершение никогда не будет выполнено.

Я не думаю, что это правда. Блок завершения будет вызываться всегда. И если вы используете сильное "я", ваш объект не будет освобожден до тех пор, пока не будет выполнен блок завершения.

Однако, если вы используете [weak self], ваш объект (временно) не сохраняется блоком завершения и может быть освобожден до того, как блок завершения будет запущен. Блок завершения все еще запущен, но self уже равен nil.

Если вы используете [unowned self] в своем обработчике завершения, ваш объект также может быть освобожден до вызова обработчика завершения, что может привести к сбою!

Я сделал пример, иллюстрирующий это.

[gif illustrating the issue

Полный исходный код можно найти на Github

Ответ 5

Как раз наоборот. Вы хотите, чтобы self продолжал существовать достаточно долго, чтобы вызывать блок завершения. Поэтому имея self сильные и сохраняются через отводящую обработчик завершения является хорошей вещью.

Беспокойство, которое обычно заставляет людей использовать weak self - это цикл сохранения. Но это не так. Цикл удержания - это когда self сохраняет закрытие, которое сохраняет self, вызывая утечку, потому что теперь self не может быть освобождено. Но это совсем не так. закрытие и, следовательно, self, сохраняются, но не self ! Так что некоторые из них сохраняются, временно, но это хорошо, неплохо.

Ответ 6

Нет необходимости использовать слабый/неизвестный в Animations, GCD или обработчике завершения, потому что:

Захваченная ими ссылка на внешний объект будет храниться только в течение фиксированного времени, что означает, что оно будет выполнено в определенный момент времени. После этого он будет освобожден, так что нет вероятности повторения цикла, что приведет к утечке памяти.

Как показывают предыдущие ответы,

Если анимация и завершение не сохраняются самостоятельно, то кто их сохраняет?

Я не нашел никаких документальных подтверждений этому, но я верю, что они сохраняются самим собой, но в течение определенного периода времени. После этого завершается выполнение и освобождает себя, что приводит к отмене выделения себя.

В сценарии сохранения цикла замыкание сохраняется самостоятельно и само замыканиями в течение неопределенного времени, что рассматривается как опорный цикл и утечка памяти.