2010-09-07 1 views
0

Я посмотрел на инструменты, и я увидел, что распределение увеличило количество удержаний на 1. Пока все ясно. Но присвоение класса моей собственности также увеличило количество удержаний до 2.присвоение имущества и распределение приводит к сохранению счета 2

self.myProperty = [[MyClass alloc] init] 

Vs.

MyClass *myCreatedVariable = [[MyClass alloc] init]; 
self.myProperty = myCreatedVariable 

Чтобы уменьшить количество удержаний до нуля, я выпустил myCreatedVariable сразу после моих звонков. Переменная экземпляра myProperty освобождается в методе dealloc. Правильно ли, что свойство только выпущено в методе dealloc?

Теперь мой вопрос:

является выделение и присвоение свойству всегда создавая сохранить счетчик 2? Поэтому не используйте

self.myProperty = [[MyClass alloc] init] 

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

Приветствия

+0

Вы никогда не увидите объект с нулевым значением удержания, потому что, как только удержание счета падает до нуля, объект освобождается. – Toastor

ответ

4

Ваше имущество, скорее всего, объявлен удерживающего или копирования:

@property (retain) MyClass myProperty; 

или

@property (copy) MyClass myProperty; 

Это вызывает ваш сеттер, который делает то, что говорят его атрибуты: сохранить! Копия также сохранится.

Хотя он сработал, вы не должны пытаться получить полезную информацию из свойства preserveCount.

Я не могу рекомендовать Memory Management Programming Guide достаточно высоко, хорошо стоит первое, второе и третье чтение. :-)

+1

'копия'. * Нет *' сохранение'. 'copy' * обычно * приводит к созданию нового (принадлежащего) объекта. Возможно, что класс может переопределить метод 'copy', чтобы просто выполнить' return [self сохранить]; ', но это детализация реализации. –

+0

ОК, ответ на вопрос: «Является ли распределение и присвоение объекту, всегда создающему счетчик сохранения 2?» нет, из-за определенного свойства сохранения. Я еще раз посмотрю на MMPG, но прежде, чем я забуду: что будет, если я не сохраню собственность? (= Почему я сохраняю свою собственность?) Как освободить сохраненное и распределенное свойство? Или используйте autorelease или сделайте что-то вроде [myProperty release]; [выпуск myProperty] ;? – testing

+0

@Dave DeLong: Ну, копия может не сохраниться - и действительно, она может просто сохранить себя для неизменяемых объектов. Но независимо от того, как это реализовано, будь то выделение или сохранение, для рассмотрения управления памятью это одно и то же. Это была моя точка зрения, поскольку мы на самом деле не знали, как было указано свойство. – Eiko

1

Создание объектов с использованием функции init возвращает по умолчанию сохраненный экземпляр. (см. Руководство по программированию управления памятью)

Если свойство определено атрибутом «Сохранить», то ваш объект сохраняется еще раз.

Так правильный способ сделать это

MyClass *myCreatedVariable = [[MyClass alloc] init]; 
self.myProperty = myCreatedVariable; 
[myCreatedVariable release]; 

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

В обоих случаях keepCount - это 1, как и ожидалось.

Если ваше свойство определено с помощью атрибута 'copy', вы также можете освободить объект и даже убить его, поскольку он был полностью скопирован и сохранен один раз. (я думаю, что есть что-то там, если вы используете сбор мусора вместо управляемой памяти ... Проверить ..)

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

Это, однако, не Рекоммендуемое использовать «присвойте атрибут», так как вы можете установить свойство с объектами, которые вы не создавали сами, и которые могут быть выпущены в любое время, позволяя вашу собственность, указывая на полях ...

Наконец, не забывайте, что статические создатели в Какао не возвращают сохраненные объекты. (Это соглашение, исключения могут существовать ...)

пример:

NSArray* myArray = [NSArray array]; 
self.myProperty = myArray; 

В этом случае не отпускайте MyArray, это уже сделано в функции создателя. Присвоение этого свойства сохраняет его. (С атрибутом сохранения или копирования).

Надеется, что это поможет,

Приветствия

+0

Спасибо, что закончили. Я уже сделал это, как в вашем первом фрагменте кода. Поэтому, если я использую addObject: для моего NSMutableArray я могу освободить его сразу после добавления. Полезно знать (я заглянул в свой код, и я уже сделал это, как вы сказали, не зная об этом). А во втором фрагменте кода я никогда не выделял/сохранял/... поэтому мне не нужно его выпускать. Хорошо, все ясно.Извините за мое неведение: Но что такое статический создатель? «Функция init возвращает сохраненный экземпляр по умолчанию»: проблема не была функцией init, проблема заключается в атрибуте alloc и сохранении. – testing

0

К сожалению? Noooo. Я боюсь, что программирование пытается узнать, что мы не знаем каждый день!

Статические создатели - это функция удобства, облегчающая распределение общих объектов. У многих классов в какао-каркасе есть такие функции. Массивы, Словарь, Пути, ...

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

+(MyClass*)myClass 
{ 
    MyClass *myNewInstance = [[myNewInstance alloc] init]; 
    return [myNewInstance autorelease]; 
} 

Затем вы можете переписать свой оригинальный пример, как:

.. 
self.myProperty = [MyClass myClass]; 
.. 

Straight! Или вы могли бы написать метод, как

-(void)myFunction 
{ 
    MyClass* myTempObject = [MyClass myClass]; 
    if (myTempObject) { 
    // do something with your temporary object 
    } 
    // Simply exit, object will be released later on. 
} 

Это гораздо короче (мы должны обрабатывать случай, когда создание объекта не удалось) ..

Обратите внимание, что это все конвенции, вы в принципе можете сделать есть вам нравится и создавать сохраненные объекты или использовать другое имя для создателя. Но безопаснее следовать правилу рамки, тогда он становится рефлексом при кодировании. См. Такие методы, как [Словарь NSDictionary], [NSArray array], [NSArray arrayWithObjects:], ...

Приветствия

+0

Большое спасибо за образование! Очень легко понять! – testing

1
@property (nonatomic, retain) NSString *strURL; 

Это будет держать сохранить счетчик = 0

При использовании аксессора для инициализации strURL затем сохранить счетчик увеличивается на 1

self.strURL = [NSString stringWithString:@"http://192.168.1.25/shop.php"]; 

Однако если вы сделал это без использования доступа, тогда ваш счетчик ссылок остался бы таким же, как 0

strURL = [NSString stringWithString:@"http://192.168.1.25/shop.php"]; 

Обратите внимание, что когда вы используете эту переменную с удержанием count как 0, автоотдел работает, и переменная освобождается, что дает ошибку «SIGABART» или «EXC_BAD_ACCESS» при попытке получить доступ к ее значению.

Обычно, когда вы используете init для инициализации своих переменных, лучше всего использовать alloc.

strURL = [[NSString alloc] stringWithString:@"http://192.168.1.25/shop.php"]; 

Надеюсь, это поможет!

Смежные вопросы