NSArray:lastObject возвращает автовыпущенный объект?

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

NSMutableArray * array;
// fill the array
NSObject * obj = [array lastObject];
[array removeLastObject];
// do something with obj (in the same function)

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

9
задан Kyle 23 May 2010 в 23:12
поделиться

3 ответа

Почему бы не вызвать

[array removeLastObject]

в конце функции? Это на один релиз / удержание меньше. Это может сделать ваш код более читабельным / менее загроможденным.

Для записи документация Apple :

Подобно NSArray, экземпляры NSMutableArray поддерживает сильный ссылки на их содержание. если ты не используйте сборку мусора, когда вы добавляете объект в массив, объект получает сообщение о сохранении. Когда объект удаляется из изменяемого массив, он получает сообщение о выпуске. Если больше нет ссылок на объект, это означает, что объект освобожден. Если ваша программа сохраняет ссылка на такой объект, ссылка станет недействительной, если вы отправляете объекту сообщение о сохранении перед удалением из массива. Например, если объект не сохраняется до того, как он будет удален из массив, третий оператор ниже может приведет к ошибке выполнения:

id anObject = [[anArray objectAtIndex:0] retain]; 
[anArray removeObjectAtIndex:0]; 
[anObject someMessage];
11
ответ дан 4 December 2019 в 13:00
поделиться
NSObject * obj = [array lastObject]; // Just returns an object, its retain count not changed
[array removeLastObject]; // object receives release message

Итак, если ваш массив - единственный объект, который сохраняет ваш объект, то после его удаления его счетчик сохранения становится равным нулю, и он должен быть освобожден. Чтобы безопасно работать с этим объектом, вы должны сохранить его и отпустить, когда он не нужен:

NSObject * obj = [[array lastObject] retain];
[array removeLastObject];
// do something with obj (in the same function)
[obj release];
2
ответ дан 4 December 2019 в 13:00
поделиться

Здесь стоит упомянуть Правила управления памятью какао . Если вы работаете в среде, отличной от GC, например iPhone, о них всегда стоит упоминать.

Основное правило гласит:

Вы становитесь владельцем объекта, если создаете его с помощью метода, имя которого начинается с «alloc» или «new» или содержит «копию» (например, alloc, newObject или mutableCopy ), или если вы отправите ему сообщение о сохранении. Вы несете ответственность за отказ от владения объектами, которыми вы владеете, с помощью выпуска или автоматического выпуска. В любой другой раз, когда вы получите объект, вы не должны его отпускать.

Очевидно, вы не получили obj с помощью alloc, new ... или чего-то, что содержит копию. Значит, ты им не владеешь.

В вашем коде также имеет значение второе следствие:

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

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

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

ETA: Только что взглянул на руководство по программированию потоков и выяснилось, что NSMutableAtrray не сохраняет, не автозапускает.

3
ответ дан 4 December 2019 в 13:00
поделиться