Рекомендуется декларировать свойства для всех ваших IBOutlets для ясности и единообразия. Подробности изложены в Руководстве по программированию управления памятью.. Основная суть заключается в том, что когда ваши объекты NIB разархивированы, код загрузки пера проходит и устанавливает все IBOutlets с помощью setValue: forKey :. Когда вы объявляете поведение управления памятью в свойстве, нет никакой загадки в том, что происходит. Если представление выгружается, но вы использовали свойство, которое было объявлено как сохранение, у вас все еще есть действительная ссылка на ваше текстовое поле.
Возможно, будет полезен более конкретный пример, чтобы указать, почему вам следует использовать удерживающее свойство:
Я собираюсь сделать некоторые предположения относительно контекста, в котором вы работаете - я предполагаю, что UITextField выше является подвидом другого представления, которое контролируется UIViewController. Я предполагаю, что в какой-то момент представление находится за пределами экрана (возможно, оно используется в контексте UINavigationController), и что в какой-то момент ваше приложение получает предупреждение о памяти.
Итак, допустим, вашему подклассу UIViewController необходимо получить доступ к своему представлению, чтобы отобразить его на экране. На этом этапе будет загружен файл пера, и все свойства IBOutlet будут установлены кодом загрузки пера с помощью setValue: forKey :. Здесь важно отметить представление верхнего уровня, для которого будет установлено свойство представления UIViewController (которое сохранит это представление верхнего уровня), и ваш UITextField, который также будет сохранен. Если он просто установлен, он будет сохранен кодом загрузки пера, в противном случае свойство сохранит его. UITextField также будет подпредставлением UIView верхнего уровня, поэтому он будет иметь дополнительное сохранение на нем, находясь в массиве подвидов представления верхнего уровня, поэтому на этом этапе текстовое поле было сохранено дважды.
На этом этапе, если вы хотите программно отключить текстовое поле, вы можете это сделать. Использование свойства делает управление памятью здесь более понятным; вы просто устанавливаете свойство с новым автоматически выпускаемым текстовым полем. Если вы не использовали свойство, вы должны не забыть освободить его и, при желании, сохранить новое. На данный момент неясно, кому принадлежит это новое текстовое поле, потому что семантика управления памятью не содержится в установщике.
Теперь предположим, что другой контроллер представления помещен в стек контроллера UINavigation, так что это представление больше не находится на переднем плане. В случае предупреждения о памяти, представление этого внеэкранного контроллера представления будет выгружено. На этом этапе свойство представления верхнего уровня UIView будет обнулено, оно будет освобождено и освобождено.
Поскольку UITextField был установлен как свойство, которое было сохранено, UITextField не освобождается, как это было бы, если бы он сохранялся только в массиве subviews представления верхнего уровня.
Если вместо этого переменная экземпляра для UITextField не была установлена через свойство, она также была бы рядом, потому что код загрузки пера сохранил ее при установке переменной экземпляра.
Один интересный момент, который здесь подчеркивается, заключается в том, что поскольку UITextField дополнительно сохраняется через свойство, вы, вероятно, не захотите сохранять его в случае предупреждения о памяти. По этой причине вы должны обнулить свойство в методе - [UIViewController viewDidUnload]. Это позволит избавиться от последней версии в UITextField и освободить ее, как задумано. Если вы используете свойство, вы должны не забыть освободить его явно. Хотя эти два действия функционально эквивалентны, цель различна.
Если вместо замены текстового поля вы решили удалить его из представления, возможно, вы уже удалили его из иерархии представлений и установили для свойства значение nil или освободили текстовое поле. Хотя в этом случае можно написать правильную программу, легко допустить ошибку чрезмерного освобождения текстового поля в методе viewDidUnload. Чрезмерное высвобождение объекта - это ошибка, приводящая к сбою; установка свойства, которое уже имеет значение nil, снова равным nil, не является.
Мое описание могло быть излишне многословным, но я не хотел упускать какие-либо детали в сценарии. Простое следование рекомендациям поможет избежать проблем, когда вы столкнетесь с более сложными ситуациями.
Также стоит отметить, что поведение управления памятью в Mac OS X на рабочем столе отличается. На настольном компьютере установка IBOutlet без установщика не сохраняет переменную экземпляра; но снова использует сеттер, если он доступен.
person
Joey Hagedorn
schedule
09.08.2009