Сохранить / освободить возвращенные объекты - PullRequest
6 голосов
/ 16 августа 2011

Я новичок в Objective-C, так что это может быть глупый вопрос.

Я не могу не увидеть сходства между ObjC и COM от Microsoft в отношении управления памятью (AddRef / Release против retain / release). В среде COM вам более или менее навязано всегда AddRef (retain) объект, прежде чем возвращать его вызывающей стороне. Из того, что я видел до сих пор (я являюсь третьим по Программирование Cocoa® для Mac® OS X (3-е издание) ), часть управления памятью несколько нечеткая.

Предполагая, что GC не существует, каков идиоматический способ вернуть объект?

Ответы [ 5 ]

12 голосов
/ 16 августа 2011

Чтение Руководство по программированию управления памятью об пулах автоматического освобождения.

В Objective-C, по соглашению, объекты должны возвращаться автоматически (если метод, возвращающий объект, не имеет имени, начинающегося с«Alloc», «new», «copy» или «mutableCopy»).Автоматически освобожденные объекты отслеживаются Objective-C в пуле и автоматически обрабатываются, что означает, что вам не нужно заботиться об отправке им окончательного выпуска.Это значительно упрощает подсчет ссылок по сравнению с COM, поэтому большую часть времени вы не видите вызовов release для возвращаемых объектов.Напротив, в том же соглашении указано, что все объекты, возвращаемые методом, имя которого начинается с alloc, new, copy или mutableCopy, являются ответственностью вызывающего метода.Вы должны вручную вызвать release для этих объектов, иначе ваша программа будет иметь утечки памяти.

7 голосов
/ 16 августа 2011

Какао преодолевает ограничения AddRef / Release в COM, вводя третьего брата; autorelease.

  • retain - Мне нужно это, заставь это остаться.
  • release - мне это больше не нужно, вы можете удалить его немедленно.
  • autorelease - мне это не нужно, но позвольте ему подождать несколько секунд, если кто-то другой захочет его забрать первым.

Это крошечное дополнение позволяет обрабатывать большинство возвращаемых значений как если бы у нас была сборка мусора. Если вы не заинтересованы в сохранении возвращаемого значения, просто не делайте ничего лишнего.

Для того, чтобы заставить это работать, существует соглашение (соглашение, достаточно хорошее, чтобы компилятор автоматически выполнял операции памяти для вас с предстоящим ARC) :

  • Имена методов, начинающиеся с этих must , возвращают сохраненные экземпляры:
    • alloc
    • copy
    • new
    • retain
  • Все остальные должны возвращать автоматически выпущенные экземпляры.

Три примера реализации того, как это можно применить на практике:

-(NSString*)newHelloWorldString {
    NSString* s = [NSString stringWithString:@"Hello world"];
    // Apply retain because s in now autoreleased
    return [s retain];
}

-(NSString*)helloWorldString {
    NSString* s = [[NSString alloc] initWithString:@"Hello world"];
    // Apply autorelease because s is now retained.
    return [s autorelease];
}

-(NSString*)fullName {
    // No memory management needed, everything is autoreleased and good.
    NSString* fn = [self firstName];
    NSString* ln = [self lastName];
    NSString* s = [NSString stringWithFormat:@"%@ %@", fn, ln];
    return s;
}
1 голос
/ 16 августа 2011

Обычно что-то вроде

return [autorelease объекта];

, и вы можете сохранить его на другом конце.

Если вы планируете развертывание на Lion / iOS5 илииспользуете последнюю версию SDK, а затем проверьте ARC.

0 голосов
/ 16 августа 2011

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

т.е.

-(void) setAnswer:(Answer*) _answer{
    self.answer = _answer; // If the answer is created from a returned message.
    [_answer release];
}

edit: я думаю, что я, возможно, поднял неправильные вещи там сейчас, когда я смотрю на него во второй раз.Имелось в виду что-то вроде:

Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];
0 голосов
/ 16 августа 2011

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

т.е. Ответ * answer = [stackoverflow getAnswer], и если ответ был создан в методе getanswer, то кто бы его ни извлекал, он отвечает за его освобождение.

Имеет смысл?

...