Лучшая практика для назначения новых объектов сохраненным свойствам?

Я использую Core Data для своего приложения для iPhone. Мои атрибуты установлены с сохраненными свойствами.

Например, атрибут «число» в сущности «Вещь»:

#import <CoreData/CoreData.h>

@interface Thing :  NSManagedObject  
{
}
@property (nonatomic, retain) NSNumber * number;
@end

@implementation Thing 
@dynamic number;
@end

При работе с объектами Thing в моем коде я устанавливал свойство числа следующим образом:

thing.number = [[NSNumber alloc] initWithInteger:1];

Однако это приводит к утечке памяти (у нового объекта NSNumber число сохранений на единицу больше, чем нужно, из-за сохранения свойства alloc plus).

Поскольку это для iPhone OS, я хотел бы сам управлять памятью, поэтому я предпочитаю не использовать пулы автоматического освобождения (что также дает более высокую производительность и меньшее максимальное использование памяти).

  1. Я знаю, что этот шаблон работает (и он уже обсуждался в нескольких сообщениях SO):

    NSNumber *num = [[NSNumber alloc] initWithInteger:1];
    thing.number = num;
    [num release];
    

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

  2. Я думаю, что это тоже сработает (но я не заметил этого ни в каких сообщениях SO):

     thing.number = [[NSNumber alloc] initWithInteger:1];
     [thing.number release];
    

    Этот шаблон менее ясен, но требует только двух строк и не использует временную переменную.

Вопрос
Существуют ли другие шаблоны для назначения новых объектов сохраненным свойствам (без использования пулов автоматического освобождения)? Какова лучшая практика здесь?


person gerry3    schedule 12.11.2009    source источник


Ответы (4)


Помимо использования пулов авторелиза, это единственные, которые я, например, видел. Я бы не стал слишком опасаться авторелиза. Они работают просто отлично, и это тот случай, когда вы, вероятно, не увидите никакой разницы в производительности.

Однако, если вы действительно хотите избежать этого, кажется, что применимой лучшей практикой здесь является «Принцип наименьшего удивления». Поскольку первая идиома встречается в большинстве примеров кода, кажется, что вам, вероятно, следует просто убрать лишнюю строку ради тех, кто поддерживает код.

person Benjamin Cox    schedule 12.11.2009
comment
Мое намерение состояло в том, чтобы не превращать это в обсуждение автовыпуска (который, по моему мнению, был достаточно освещен на SO). Хороший вопрос о принципе, но я буду поддерживать его, так что любой метод должен работать. - person gerry3; 12.11.2009

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

Кстати, второй шаблон тоже должен работать нормально.

person Mihai Damian    schedule 12.11.2009
comment
Мое намерение состояло в том, чтобы не превращать это в обсуждение автовыпуска (который, по моему мнению, был достаточно освещен на SO). Я согласен, что у моего приложения почти наверняка не возникнет проблем даже при широком использовании объектов авторелиза для моих атрибутов Core Data. +1 на ваше рассмотрение. - person gerry3; 12.11.2009

Пулы автоматического освобождения не должны использовать значительно больше памяти, если только вы не создаете много объектов в тесном цикле.

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

Лично я бы определенно использовал пулы автовыпуска, если только у меня не возникнут проблемы с производительностью или памятью.

person Thomas Müller    schedule 12.11.2009
comment
Мое намерение состояло в том, чтобы не превращать это в обсуждение автовыпуска (который, по моему мнению, был достаточно освещен на SO). Я согласен, что у моего приложения почти наверняка не возникнет проблем даже при широком использовании объектов авторелиза для моих атрибутов Core Data. - person gerry3; 12.11.2009

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

вещь.номер = [номер NSNumberWithInt:1];

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

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

Вместо этого шаблон 2 кажется мне неверным по следующей причине: вы сначала присваиваете NSNumber своему свойству, а затем освобождаете свое свойство. Однако вам необходимо освободить номер NSN, который вы выделили, а не тот, который был сохранен вашим свойством (вы сделаете это позже, еще раз, когда закончите со свойством). Чистым эффектом шаблона 2 должна быть утечка памяти (выделенный NSNumber не освобождается) и ваше свойство не содержит NSNumber (поскольку вы сначала сохранили его, а затем освободили).

person Massimo Cafaro    schedule 12.11.2009
comment
Для шаблона 2 по-прежнему существует только один объект, и его счетчик сохранения правильно уменьшен. Помните: ссылки (указатели) на объекты не имеют счетчиков сохранения, объекты имеют счетчики сохранения. - person gerry3; 12.11.2009
comment
Хорошо, это имеет смысл. Есть ли документ Apple, в котором это обсуждается более подробно? Заранее благодарим вас за то, что поделились этим. - person Massimo Cafaro; 12.11.2009