Разработка для iPhone: как отловить исключение / NSError в Objective-C? - PullRequest
9 голосов
/ 01 августа 2009

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

-(void)testException
{
    @try
    {
        NSString* str;
        [str release];
    }
    @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }
}

Я знаю, что это не работает. Потому что release никогда не вызывает исключение. Вот мои вопросы:

  1. Как достичь этой цели, ошибка будет зафиксирована, без сбоев?
  2. Как узнать, какая системная библиотека вызовет исключение, и чтобы я мог написать некоторый код и узнать, как он работает?

Вот что я прочитал

  • а. Темы программирования исключений для Какао
  • б. Программирование обработки ошибок
    Руководство по какао

Я из опытного программиста Microsoft, в котором исключение или неожиданное исключение всегда предотвращало сбой моей программы в очень плохой среде.

Как вы, ребята / девчонки (программисты Mac Genius), создали программы без сбоев? Поделитесь своим опытом.

Ответы [ 3 ]

12 голосов
/ 11 ноября 2009

Objective-C - неуправляемая среда выполнения; код, который вы компилируете, запускается непосредственно на процессоре, а не на виртуальной машине. Это означает, что у вас нет контрольного уровня, который может перехватывать все возможные режимы отказа, как при работе в .NET VM или JVM. Суть в том, что единственный способ убедиться, что программа не может завершиться сбоем, - это очень тщательно кодировать и очень тщательно тестировать. И даже тогда вы не уверены, вы просто так думаете.

В последней версии Xcode интегрирован статический анализатор Clang («Построить и проанализировать» в меню «Построение»), который может идентифицировать некоторые классы потенциальных ошибок - я вполне уверен, что он, например, пометит ваш пример выше). Но здесь нет волшебной пули; Единственное решение - тяжелая работа.

4 голосов
/ 01 февраля 2010

Тестовый тест Тестовый тестовый тест

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

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

Конечно, бывают ситуации, когда невозможно гарантировать, что вызов метода не вызовет исключения, и вам нужно быть готовым, но завершение всего в блоки @ try / @ catch определенно не является решением.

3 голосов
/ 02 августа 2009

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

Если вы пройдете по своему коду, я почти гарантирую, что ваш выпуск вызывается по nil, что в Objective-C полностью допустимо.

Попробуйте сделать это:

NSString *str = [[NSString alloc] initWithString:@"a string"];
[str release];
[str release];

Вызов release не освобождает объект, он просто уменьшает счет сохранения на 1. Когда счет сохранения объектов равен 0,

[self dealloc];

вызывается автоматически.

Если приведенный выше код не генерирует исключение немедленно, это может быть связано с тем, что фактическое сообщение об освобождении откладывается в какой-то момент в будущем (я не уверен точно, когда dealloc вызывается после того, как число сохранений достигает 0. I думаю, что он вызывается немедленно и в том же потоке, но какой-нибудь другой ниндзя Какао точно об этом узнает).

Что вы можете сделать, это добавить категорию в NSObject, внедрить методы dealloc и release и попытаться обнаружить, что вы там исключение.

- (void)dealloc{

 @try
    {
        [super dealloc];
    }
 @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }

}



- (void)release{

     @try
        {
            [super release];
        }
     @catch(NSException* ex)
        {
            NSLog(@"Bug captured");
        }

    }

Дополнительным бонусом является то, что этот код будет действителен для каждого объекта в вашем приложении, поскольку это категория в NSObject.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...