Могу ли я вернуть выделенный объект и освободить его вне функции?

- (NSString *)allocString{
    NSString *str = [[NSString alloc] init];
    return str;
}

- (void)viewDidLoad{
    NSString *name = [self allocString];

    [name release]; // Can I release an object here?
}

Привет, я только что написал простой пример, используя NSString. В моей реальной программе вместо NSString я использовал собственный класс UIView.

allocString создает один экземпляр NSString, и его счетчик удержания равен 1. Без автоматического освобождения он просто возвращает экземпляр.

В методе viewDidLoad переменная name просто указывает на объект, возвращаемый методом allocString, поэтому счетчик сохранения экземпляра по-прежнему равен 1.

Таким образом, [name release] уменьшает счетчик удержания.

Это правильно? Или мне нужно автоматически выпустить его в методе allocString? Спасибо!


person pnmn    schedule 29.03.2011    source источник


Ответы (3)


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

Но то, что вы делаете, необычно. Если вы хотите, чтобы объект продолжал существовать в течение всего срока существования метода (чтобы вы могли return и получить его от вызывающего метода), тогда вам следует использовать autorelease.

В вашем примере первый метод, вероятно, не должен сохранять право собственности на строку. Он должен отпустить его и позволить вызывающему абоненту поднять трубку. Но, конечно, если вы release это в методе, он будет немедленно освобожден. Так что вместо этого вы можете autorelease это. При автоматическом освобождении ваш первый метод говорит: «Мне больше не нужен этот объект, и я отказываюсь от владения, но, пожалуйста, оставьте его в памяти еще немного, чтобы мой вызывающий пользователь мог сохранить его, если потребуется».

Вот пример:

- (NSString *)createString {
    /* Create a string. This method owns it. */
    NSString *str = [[NSString alloc] init];

    /* Autorelease it. This method does not own it, but wants it to stay in memory temporarily. */
    [str autorelease]

    /* Return it. It will stay in memory till the end of the current run loop */
    return str;
}

- (void)viewDidLoad{
    NSString *name = [self createString];
    /* We now have a copy of the string. Nobody owns it. */
    /* It is due to be released at the end of the current run loop. */

    /* If we want to take ownership of it and prevent deallocation, we should retain it. */
    [name retain];
}

Это поведение используется во всех API-интерфейсах Какао. Когда вы видите методы класса, возвращающие новый объект, этот объект будет автоматически выпущен. Например, когда вы вызываете [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil], вы просите класс NSArray создать для вас массив. Если существует за пределами метода arrayWithObjects: благодаря своему автоматически выпущенному статусу. Если вы этого не сделаете retain, он будет выпущен в конце текущего цикла выполнения.

person Simon Cave    schedule 29.03.2011
comment
Его первое имя метода начинается с alloc - по соглашению он должен возвращать объект, которым владеет вызывающий. - person Sherm Pendley; 29.03.2011
comment
Тогда почему мы не сохраняем новый экземпляр массива после этого: NSArray * a = [NSArray arrayWithObjects: @ 111, @ 222, nil]; ? (например: [сохранить];) - person Almas Adilbek; 04.03.2012

Если вы просто замените имя метода «allocString» на «newString», он будет работать нормально. В объекте C есть соглашение об использовании таких методов. Это соглашение заключается в том, что имя метода должно начинаться с «new *», и это не приведет к утечке памяти.

person Satyam    schedule 29.03.2011

Да, все, что у вас есть, будет работать нормально.

person Carl Norum    schedule 29.03.2011
comment
Вы неправы. попробуйте создать аналогичный код, и в XCode Build & Analyze он покажет вам две утечки памяти. - person Satyam; 29.03.2011
comment
@Satyam: Почему он не прав? Строка выделяется один раз и освобождается один раз. Это нормально, хотя для метода allocString обычно используется автозапуск. - person Vagrant; 29.03.2011
comment
Вы могли заметить утечки памяти при сборке и анализе. Если вы видите объективные соглашения C, ваш ответ правильный, если имя метода начинается с new. Но имя метода не начинается, и это приведет к утечкам. Хотя оба дадут вам два указателя, либо используйте метод, начинающийся с new, либо вам нужно автоматически освободить его в методе allocString. - person Satyam; 29.03.2011
comment
@Satyam - утечки памяти нет. Это ложное срабатывание анализатора. Я согласен с вами, что код OP нестандартен, но, конечно, в нем нет никаких ошибок. - person Carl Norum; 29.03.2011