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

Я создаю все свои экранные объекты программно и добавляю их в подкатегории моих сцен.

Например:

let button: ******** = ********( frame: CGRect( x: 0, y: 0, width: 160, height: 50 ) )
self.view.addSubview( button )

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

Изменяя сцену раскадровки, я имею в виду через текущий контроллер представления, например:

self.presentViewController( targetController, animated: true, completion: nil )

Поэтому, с учетом сказанного, мой вопрос:

1) Удаление объектов может быть выполнено следующим образом:

button.removeFromSubview()
button = nil

верный?

2) Есть ли способ удалить любой объект, вставленный в представление subview в цикле, и также назначить ему nil для полного удаления любых ссылок, связанных с объектом? Я могу удалить их один за другим, но это задача, связанная с болью.

3) Есть ли все-таки, чтобы объекты автоматически удалялись из памяти после смены сцен? Это было бы лучшим решением.

Примером решения было бы лучше всего.

Заранее спасибо.

2 ответа

Некоторые вещи, которые могут быть уточнены:

1) Кнопки, которые добавляются через раскадровку (тегированные @IBOutlet), слабы; вам не нужно их обманывать, потому что ваша ссылка на них не хранит их в памяти.

2) presentViewController вероятно, не ведет себя так, как вы ожидаете. Самое главное, не заменяет существующий контроллер вида новым контроллером представления; он "представляет" новый контроллер представлений из старого контроллера представлений. Чтобы проиллюстрировать это, вы можете вызвать self.presentingViewController с нового контроллера представления, который предоставит вам ссылку на предыдущий контроллер представления; он все еще в памяти.

Тем не менее, контроллеры просмотра не очень большие, и они имеют свои представления, разгруженные, когда их нет на экране. Если, однако, вы держитесь за некоторые большие ресурсы в представлении контроллера представления, они будут сохраняться. Я бы предложил обратиться к этому, загрузив эти активы в viewWillAppear/viewDidAppear (вместо viewDidLoad), а затем выгрузив их либо в файл readyForSegue: либо в viewDidDisappear (я думаю, что существует некоторая давняя проблема с didDisappear, которая не получает вызов последовательно? У меня есть своего рода умственное флаг, но я не уверен, что источник...)

В качестве альтернативы, если вы действительно хотите сделать это, чтобы полностью перейти на новый контроллер корневого представления, вы можете сделать это через свойство AppDelegate.window, например:

let storyboard = UIStoryboard(named: "NewStoryboard", bundle: nil)
let newVC = storyboard.instantiateInitialViewController
UIApplication.sharedApplication().delegate.window.rootViewController = newVC

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


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

for sv in view.subviews {
 sv.removeFromSuperview()
}

licensed under cc by-sa 3.0 with attribution.