Сохранение аргумента NSArray - почему? - PullRequest
1 голос
/ 14 февраля 2012

Я пытался искать, но не мог найти никакой помощи.

- (NSArray *)sushiTypes {
    return _sushiTypes;
}

- (void)setSushiTypes:(NSArray *)sushiTypes {
    [sushiTypes retain];
    [_sushiTypes release];
    _sushiTypes = sushiTypes;
}

Хотелось бы узнать, пока я работал в этом учебнике, я не могу понятьпочему он сохраняет аргумент.Я попытался закомментировать это заявление о сохранении, и программа работает так же, без утечек.Так это просто не нужно?

Я также хотел бы добавить тот факт, что я вызвал такой метод

self.sushiTypes = [[NSArray alloc]initWithObjects:"objects...];

Но когда я отлаживаю его, вместо того, чтобы перейти к -(NSArray *) метод sushiTypes, он идет к методу setSushiTypes.Почему это?

Ответы [ 4 ]

4 голосов
/ 14 февраля 2012

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

Важно отметить порядоксообщения в сеттере также.Сначала необходимо вызвать

[sushiTypes retain];

, поскольку _sushiTypes и sushiTypes могут указывать на один и тот же объект.Если вы поменяете их местами и сначала вызовете команду release, память может быть освобождена до того, как вы получите право требовать владения.

2 голосов
/ 14 февраля 2012

Причина, по которой автор ставит сохранение, заключается в том, что это стандартный синтаксис сеттера для свойства retain.В ObjC объект должен быть сохранен , если только мы не уверены, что какой-то другой объект будет отвечать за его сохранение (сохраняя его).

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

 self.sushiTypes = [[[NSArray alloc] initWithObjects:one, two, three, nil] autorelease];

, потому что объект возвращается с счетом сохранения 1. Google NARC и target-c, которые могут привести вас сюда .У метода, который вызывает сеттер , есть для освобождения (или, лучше, автоматического выпуска), потому что он скоро потеряет способность делать это, и у вас будет утечка.

Даже с исправлением,ваш метод setter будет работать без сохранения, потому что автоматическое освобождение произойдет позже.

Этот метод set вызывается при вызове набора из себя или из другого объекта с использованием явного синтаксиса:

 [self setSushiTypes:whatever];

или неявный синтаксис:

 self.sushiTypes = whatever;

Примечание. Сеттер вызывается при использовании self.sushiTypes =, даже если не объявлено @property.

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

0 голосов
/ 14 февраля 2012

Это сеттер, и я приведу вам пример. Предположим, что _sushiTypes ivar указывает на objA, и теперь вы хотите установить свой ivar на новый объект, скажем, objB, т.е. он передает в качестве аргумента sushiTypes.

1. Затем в своем установщике вы сохраняете objB, так как устанавливаете его на ivar и хотите получить право собственности. так ты пишешь [sushiTypes retain];

2. Затем вы освобождаете старый объект (потому что вы собираетесь установить новый объект, т.е. objB на ivar), который вы сохранили с помощью того же установщика. Итак, вы выпустили старый объект [_sushiTypes release];, а затем присвоили сохраненный объект _sushiTypes ивару.

0 голосов
/ 14 февраля 2012

Да, точнее, вероятно, он инициализирует счетчик хранения равным 1.

Это то же самое, что наличие [sushiTypes retain].Я знаю, что если мы вызовем retain, объект будет удерживаться до тех пор, пока мы его не отпустим.

Не то же самое.Это увеличит количество сохраняемых кадров в два раза.Нет особой причины увеличивать счет дважды в одном и том же месте.Если вы это сделаете, вы будете ответственны за повторный вызов release.

У вас есть сохраненные sushiTypes.Этот sushiTypes был передан функции в качестве аргумента.Позже в функции вы выпустили его.Это освободит память о sushiTypes?в противном случае sushiTypes больше не существует.

Во-первых, вы должны убедиться, что понимаете, освобождает ли релиз память или нет, зависит от того, есть ли другие владельцы, которые имеют ссылку на объект.Если [_sushiTypes release] удерживал объект более чем в одной вещи, тогда освобождение не освобождает память в этом случае.

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

сохранить (или выделить) переменные экземпляра, освободить их в dealloc или ранее.при необходимости сохраните (или выделите) локальные переменные и отпустите их перед выходом из метода.Вызывающая сторона не владеет возвращаемым значением функции.Это подразумевает, что вы обрабатываете возвращаемое значение функции, как локальную переменную, но автоматически освобождаете его, прежде чем возвращать, а не освобождать.Это гарантирует, что оно продлится, по крайней мере, достаточно долго, чтобы вызывающая сторона могла сохранить его, если это необходимо.Один из шаблонов заключается не в том, чтобы вызывающий метод мог владеть ссылкой на аргумент метода, а в том случае, когда функция возвращает вызывающий объект, которому не принадлежит ссылка.Метод не должен освобождать ссылку вызывающей стороны.

Следуйте 2.1, вместо выпуска sushiTypes.Я создал локальную переменную NSArray * sushiTypes = _sushiTypes.Если я выпустил sushiTypes, он также выпустит sushiTypes.Или, если я сохраню sushiTypes, он также сохранит _sushiTypes.

Сохранение и освобождение отправляются объектам, а не ссылкам.sushiTypes и _sushiTypes ссылаются на один и тот же объект, поэтому для одного и того же вызова вызывается retain или release, как и для другого.

Допустимо, но, вероятно, нет необходимости [sushiTypes retain], а затем в том же методе [_sushiTypes release.Но не делайте только [выпуск sushiTypes], тем самым экспроприируя собственность _sushiTypes над объектом.

...