ObjC: Насколько плохо напрямую назначать свойство и освобождать его? - PullRequest
1 голос
/ 18 февраля 2010

Мне интересно, насколько плохим является следующий код для опытных программистов на языке C.

self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];

Это определенно менее многословно

ASIHTTPRequest *tmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = tmp;
[tmp release];

Но я не уверен, достаточно ли это значимо или не приводит к ошибкам.

Что ты думаешь?

UPDATE: Я не хочу использовать пулы автопереключения, так как мое приложение будет работать на iphone, где память ограничена.

Ответы [ 4 ]

2 голосов
/ 18 февраля 2010

ОБНОВЛЕНИЕ: я не хочу использовать пулы с автопереключением, так как мое приложение будет работать на iphone, где память ограничена.

Используйте авто-релизные бассейны! Какао Touch Touch сама использует их; создание одного или двух autorelease 'ed объектов самостоятельно не меняет общую картину.

Это правда, что Apple предостерегает вас от чрезмерной зависимости от пулов автоматического выпуска на iPhone, например от размещения сотен объектов до того, как пул истощится после завершения отправки события, но чрезмерное избегание Авто-релизы бассейнов также контрпродуктивны!

Нет ничего черного и белого; Нирвана находится в середине пути .

1 голос
/ 18 февраля 2010

Почему не это?

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];

Или, если это класс, который вы написали или у которого есть источник, создайте новый метод класса (не экземпляр), который по сути делает то же самое (предполагая NSURL * аргумент):

+ (ASIHTTPRequest *) requestWithURL:(NSURL *)url
{
     return [[[self alloc] initWithURL:url] autorelease];
}
1 голос
/ 18 февраля 2010

Определенно используйте последнее, хотя вместо tmp выберите более описательное имя.Вы несете ответственность за освобождение tmp, но не несете ответственности за освобождение self.request, по крайней мере, не в указанном контексте.

В качестве альтернативы, если вы не возражаете, добавление вещей в пул автоматического выпуска, простоделать:

self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];

или

self.request = [ASIHTTPRequest requestWithURL:url];
0 голосов
/ 18 февраля 2010

То, что вы пропустили, это не разница в многословности, а разница в управлении памятью.

Вы часто видите такой код:

ASIHTTPRequest * requestTmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = requestTmp;
[requestTmp release];

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

  • Это означает, что вы создаете новый request, refcount равен 1.
  • self.request = request, теперь, если setRequest выглядит так:

    - (void)setRequest:(ASIHTTPRequest*)aReq
    {
        [aReq retain];
        [request release];
        request = aReq;
    }
    

    Это означает, что объект сохранил requestTmp, который вы передали, и освободил старый. Пересчет requestTmp теперь 2.

  • После этого вызова вы можете освободить свой исходный requestTmp, который вы создали, и вы в безопасности, потому что объект сохранил requestTmp - повторный счет равен 1.

Однако, если вы сделаете это:

self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];

в итоге вы отпускаете request, который объект retained использует для его использования. Обратите внимание, что вы используете внутренний объект request, в котором в исходном случае вы выпустили tmp, но объект сохраняет свою собственную сохраненную ссылку.

Таким образом, результат отличается от исходного кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...