Утечка памяти при добавлении подпредставления

При добавлении подпредставления кажется, что происходит утечка контроллера представления.

Почему следующая надпись "Что"

import UIKit

final class ViewController: UIViewController {

    private lazy var mySwitch: UISwitch = {
        let mySwitch = UISwitch()
        mySwitch.tintColor = .blue
        return mySwitch
    }()

    func setup() {
        view.addSubview(mySwitch)
    }

    @objc func switchChangedState() {

    }

    deinit {
        print("what")
    }
}

var controller: ViewController? = ViewController()
controller = nil

Но следующее не

var controller: ViewController? = ViewController()
controller?.setup()
controller = nil

Редактировать: добавление GIF

Утечка памяти при добавлении подпредставления

Xcode версии 9.4.1 (9F2000)

Почему окончательный?

Tom Schulz 05.09.2018 03:04

Привет, @TomSchulz. Пишу финал по привычке. В данном конкретном примере это не нужно. При этом я бы порекомендовал добавить final, как привычку, пока вы не будете готовы поддерживать подклассы.

Jonesy 06.09.2018 09:42

Не согласен. В любом случае, вы не можете отправить файл заголовка и библиотеку. Если кто-то хочет, чтобы что-то не было окончательным, они просто редактируют ваш код. «Поддержка подкласса»; язык поддерживает создание подклассов.

Tom Schulz 10.09.2018 13:04

@TomSchulz, я не понимаю, что вы имеете в виду под «отправкой файла заголовка и библиотеки» или «просто отредактируйте свой код».

Jonesy 11.09.2018 12:05

@TomShulz Я рекомендую добавить final, если вы не готовы поддерживать подклассы. Конечно, вы и другие можете изменить эту идею в будущем. Измените его, когда будете готовы создать подкласс. Кроме того, добавление final - это улучшение производительности. developer.apple.com/swift/blog/?id=27

Jonesy 11.09.2018 12:06

Я имею в виду, что тот, кто будет работать с вашим кодом, не будет работать с C dot h fle и библиотекой компиляции (например, lib.a), и если они хотят создать подкласс, все, что нужно сделать другому программисту, это отредактировать ваше 'final' ключевое слово и он уехал на скачки. OTOH, я не знал, что final был быстрее, хотя мне интересно, сколько сэкономлено.

Tom Schulz 13.09.2018 14:32

Если кто-то попытается создать подкласс окончательного класса, хотя этого не следует делать, компилятор предотвратит успешную сборку. Это полезно. Если другой разработчик хочет создать подкласс класса, который объявлен как final, то, вероятно, этот другой разработчик тщательно изучил этот класс и счел его подходящим для создания подкласса. Или внес в класс необходимые изменения, чтобы можно было безопасно удалить final. Если вы не доверяете этому другому разработчику, вам следует исключить его или ее из команды.

Jonesy 14.09.2018 15:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
186
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш код хорош. controller?.setup() не вызовет утечки. Убедитесь, что код в тестовом примере 2 действительно вызван или нет. (Не называйте "что" напечатано)

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

Pete Morris 05.09.2018 04:27

Привет @PeteMorris. Я согласен, код определенно предполагает, что здесь нет цикла сохранения, но поведение, которое я вижу, говорит об обратном. Добавили гифку для демонстрации.

Jonesy 06.09.2018 09:37

Привет, @YunCHEN добавил гифку к посту.

Jonesy 06.09.2018 09:38

@Jonesy Это как-то связано с игровой площадкой, с вашим кодом все в порядке. Возможно, это ошибка, или, возможно, игровая площадка по какой-то причине сохранила ваш контроллер. Если вы запустите тот же самый код в реальном проекте Xcode, деинициализатор обязательно будет запущен в обоих случаях: imgur.com/a/QkLn6Q3

Pete Morris 06.09.2018 09:53

Спасибо, @PeteMorris примет, если вы сделаете официальный ответ

Jonesy 06.09.2018 10:05

@Jonesy, как сказал Пит Моррис, в PlayGround могут быть некоторые ошибки, из-за которых ваш контроллер не работает. Чтобы доказать это, добавьте controller = ViewController() дважды в конце (после controller = nil), вы получите напечатанное «что», что означает, что прежний контроллер действительно выпущен. Так что это не цикл сохранения.

Yun CHEN 06.09.2018 10:12
Ответ принят как подходящий

В вашем коде нет ничего плохого. Здесь нет цикла сохранения.

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

Если вы выполняете свой код в реальном проекте Xcode (либо в симуляторе iOS, либо на устройстве), инициализатор выполняется в обоих случаях:

deinit executes in both cases

Другие вопросы по теме