Подходящее время для использования сохраняемого сообщения?

спасибо за просмотр этого поста, было бы здорово, если бы вы, ребята, могли мне помочь. Я выполнял кое-какие задания с target-c и узнал о способе управления памятью с помощью target-c, например, обязательно вызывать выпуск всякий раз, когда я владею объектом, когда вызывать автовыпуск и т. д. Я также не хочу использовать ARC или недавно представил GC, потому что мне нравится управлять своей собственной памятью, я планирую позже перейти к разработке iOS, и я знаю, что управлять собственной памятью — хорошая практика. Но есть еще одна маленькая деталь, в которой я, кажется, уперся в кирпичную стену. Она связана с отправкой объектам сообщения -retain. Я узнал, что отправка сообщения -retain увеличивает счетчик ссылок на 1. Но будет ли это подходящим моментом для отправки -retain? :

      - (void) setName : (NSString* ) theName 
      {
          // name is an instance variable of type NSString
          [theName retain]; // Must release this
          name = [theName copy]; // Must release this in dealloc
          [theName release]; // decrement the reference count because of retain
      }

Должен ли я вызвать здесь сохранение, чтобы временно владеть аргументом и гарантировать, что он не будет каким-то образом освобожден, прежде чем я смогу его использовать?

Любая помощь будет оценена по достоинству! Спасибо!


person Alejandro    schedule 17.11.2012    source источник


Ответы (1)


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

Это описано в документации Apple на этой странице в разделе «Избегайте освобождения используемых вами объектов». Конкретно:

Политика владения Cocoa указывает, что полученные объекты обычно должны оставаться действительными во всей области действия вызывающего метода. Также должна быть возможность вернуть полученный объект из текущей области, не опасаясь его освобождения. Для вашего приложения не должно иметь значения, что метод получения объекта возвращает кэшированную переменную экземпляра или вычисленное значение. Важно то, что объект остается действительным столько времени, сколько вам нужно.

Кроме того, вам действительно следует подумать об использовании ARC. Нехорошо управлять собственной памятью. Независимо от того, насколько хорошо человек может управлять своей собственной памятью, компилятор LLVM все равно лучше. Управление собственной памятью приведет к трудноустранимым проблемам, вызванным только вами. Это дополнительный уровень когнитивной нагрузки, с которым вам действительно не нужно иметь дело, и когда вы, наконец, откажетесь от ручного управления памятью, вы вздохнете с облегчением от всех умственных накладных расходов, о которых вы даже не подозревали.

person jackslash    schedule 17.11.2012
comment
arc больше не заботится об управлении памятью. это упрощает многие вещи, но также иногда создает новые проблемы.. в любом случае, просто слово предостережения, чтобы не впасть в эйфорию :D -- тем не менее, это того стоит arc - это круто! - person Daij-Djan; 17.11.2012
comment
Нет, вы не владеете аргументами. И это неправда, что он не будет выпущен, по крайней мере, до тех пор, пока ваш метод не вернется. Только гарантируется, что объект действителен при вызове метода. Но ваш метод все еще может сделать что-то, что косвенно приведет к его освобождению. - person newacct; 19.11.2012
comment
На практике, если аргумент метода был освобожден и впоследствии освобожден во время метода без вашей явной инструкции, я бы сказал, что вы делаете это неправильно. - person jackslash; 19.11.2012
comment
@jackslash: я не знаю, что вы подразумеваете под явной инструкцией, но часто неочевидно, что то, что делает метод, может каким-то образом вызвать освобождение его аргумента. - person newacct; 19.11.2012
comment
@newacct Я хочу быть просветленным. У вас есть примеры? Или ссылку? - person jackslash; 19.11.2012
comment
Рассмотрим что-то вроде этого: -(void)doSomethingWith:(NSMutableArray *)arr andPrint:(id)x { NSLog(@"%@", x); [arr removeLastObject]; NSLog(@"%@", x); // Uh oh } -(void)test { id foo = [[NSObject alloc] init]; NSMutableArray *arr = [NSMutableArray arrayWithObject:foo]; [foo release]; id x = [arr lastObject]; [self doSomethingWith:arr andPrint:x]; } - person newacct; 19.11.2012
comment
Технически правильным шаблоном для использования будет [foo autorelease] или выполнение [foo release] после вызова -doSomethingWith:andPrint:, поскольку -(void)test по-прежнему использует эту ссылку на foo при вызове метода и, следовательно, должен по-прежнему владеть ею. Это пример неправильного выполнения. Я отсылаю вас к документации в моем обновленном ответе. - person jackslash; 20.11.2012