Как предотвратить утечку при создании исключения в init?

Вот ситуация. Скажем, у меня есть класс под названием MYFoo. Здесь он инициализатор:

-init
{
  self = [super init];
  if (self)
  {
    // during initialization, something goes wrong and an exception is raised
    [NSException raise ...];
  }
  return self;
}

Теперь где-то еще я хочу использовать объект MYFoo, поэтому я использую общий шаблон:

MYFoo *foo = [[[MYFoo alloc] init] autorelease];

Но что произойдет, так это то, что даже если есть попытка/уловка во 2-й части, будет выделен объект MYFoo, будет выведено исключение, пропущено авторекламу и неинициализированный объект MYFoo.

Что должно произойти здесь, чтобы предотвратить эту утечку?

Ответ 1

Apple Docs говорят, что лучшая практика - это не бросать.

Обработка отказа инициализации

В общем случае, если есть проблема во время метода инициализации вы следует вызвать [self release] и вернуться ноль.

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

Ответ 2

ongle на 100% прав. Но если вам нужно выбросить исключение, и вы захотите его где-то поймать (в отличие от того, чтобы просто избавиться от приложения), вы можете обернуть свою инициализацию в @try { ... } @finally { ... }

-init
{
   self = [super init];
   if (self)
   {
       @try
       { 
           // during initialization, something goes wrong and an exception is raised
           @throw...
       }
       @finally
       {
           [self release]; 
       }
   }
   return self;
}

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