Как мне обрабатывать сбой в методе init: в Objective-C?

Допустим, я создаю новый класс для iPhone в Objective-C. В одном из моих методов инициализации я хочу вручную выделить часть памяти. Итак, у меня могло бы получиться что-то вроде этого:

- (id)initWithSomeObject:(SomeObject *)someObject {
  self = [super init];
  if (self != nil) {
    myObject = someObject;
    [myObject retain];
    if ( (memory = calloc(1, sizeof(SomeStruct)) == NULL) {
      // What should I do here to clean up
      [self release];
      self = nil;
    }
  }
  return self;
}

Теперь, если предположить, что calloc () может дать сбой и что неспособность выделить память катастрофична для моего объекта, что мне делать внутри if-body, чтобы правильно очистить? Есть ли идиома или шаблон Objective-C, которые мне следует использовать?

Изменить: я включил код, опубликованный Робом Напьером. Но мне все равно нужно выпустить myObject, верно? Или добавленный код каким-то образом вызывает dealloc ()?


person Rob Jones    schedule 06.01.2010    source источник
comment
Не беспокойтесь о том, запускает ли он dealloc (). Есть, но не в этом суть. Дело в том, что [self release] уравновешивает предыдущий вызов + alloc, поэтому все ваши требуемые релизы были выполнены, и теперь система позаботится об освобождении в нужное время. В большинстве случаев наиболее подходящим временем является вызов [самовосстановления], но это может быть и позже, если есть какие-либо незавершенные автоматические выпуски. Но приведенный выше код верен и больше ничего не требуется.   -  person Rob Napier    schedule 07.01.2010
comment
В качестве побочного примечания: я понимаю, что calloc / malloc никогда не вернет NULL, система просто убьет ваше приложение, когда у вас закончится или будет мало памяти. Думаю, Apple решила, что это было проще сделать, когда приложение вылетало из-за непроверенных указателей NULL / nil.   -  person Roger Gilbrat    schedule 30.11.2011


Ответы (3)


Да, вы должны освободить себя, а затем вернуть nil.

[self release];
self = nil;

См. Проблемы с инициализаторами в Руководстве по концепциям программирования на Objective-C.

person Rob Napier    schedule 06.01.2010

Вам нужно очистить все, что вам нужно, а затем установить ссылку на себя nil. На портале Apple Dev есть статья:

Ссылка

person psychotik    schedule 06.01.2010
comment
Не забывайте отпускать себя, иначе вы протечете. (Не знаю, кто проголосовал против; вы правы). - person Rob Napier; 07.01.2010

Я просто попробовал. -dealloc вызывается из-за [self release], поэтому myObject не нужно будет выпускать в initWithSomeObject. Конечно, вы можете переместить myObject = [someObject retain]; (я предпочитаю этот стиль на тот случай, если -retain может выйти из строя по какой-либо причине) ниже вызова, который может потерпеть неудачу (если это возможно).

person MrMage    schedule 06.01.2010