Отладка — это искусство обнаружения ошибок во время выполнения приложений. Это искусство можно разделить на два основных метода: грубая отладка и остановка во время выполнения.

Грубая отладка (caveman debugging) предусматривает изменение кода, обычно временное, как правило, путем добавления кода для выдачи информативных сообщений на консоль. Консоль можно просматривать на панели Debug (в главе б описан метод вывода информации на консоль на отдельной вкладхе).

Стандартной командой отсылки сообщения на консоль является команда NSLog. Это функция языка С, получающая аргумент типа NSString, представляющий собой строку, за которой следуют аргументы форматирования.

Строка форматирования — это строка (в данном случае объект класса NSString), содержащая символы, называемые спецификаторами формата, значения которых (аргументы формата) подставляются во время выполнения приложения. Все спецификаторы формата начинаются с символа (%), так что единственный способ ввести литерал процента — использовать двойной знак процента (%%). Символ(ы), следующий за знаком процента, задает тип значения, которое будет подставлено во время выполнения программы. Наиболее распространенными спецификаторами формата являются символы %8 (ссылка на объект), %d (целое число) и %f (число типа double). Рассмотрим следующий пример:

NSLog(9"the window: self.window);

В данном примере self. window — это первый (и единственный) аргумент формата, поэтому его значение заменит первый (и единственный) спецификатор формата %@, когда строка форматирования будет выводиться на консоль. Таким образом, вывод на консоль будет выглядеть примерно следующим образом (для ясности я его слегка отформатировал):

the window: <UIWindow: 0х8а68а60;

frame - (0 0; 320 480); hidden - YES;

gestureRecognizers - <NSArray: 0x8a69fd0>; layer - <UIWindowLayer: 0x8a697b0>>

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

описания в классе UlWindow: этот метод вызывается, когда объект используется вместе со спецификатором формата %0. По этой причине вы, возможно, захотите реализовать описание в своих собственных классах, чтобы формировать краткое описание с помощью вызова функции NSLog.

Для того чтобы увидеть полный список спецификаторов формата, доступных для строки форматирования, прочитайте документ компании Apple String Format Specifiers (в справочнике String Programming Guide). Спецификаторы формата в большой степени основаны на стандартной функции printf из библиотеки языка С; ее описание можно найти на справочной странице sprintf в стандарте K&R В1.2 и спецификацию функции printf, разработанную IEEE. В справочном руководстве есть ссылки на эти страницы.

Основной ошибкой при работе с функцией NSLog (и любой строкой форматирования) является передача неправильного количества аргументов форматирования или значений аргумента неправильного типа, который отличается от типа спецификатора формата. Новички жалуются на то, что система регистрации ошибок часто объявляет определенное значение бессмысленным, хотя на самом деле бессмысленным является сам вызов функции NSLog; например, если спецификатор формата был равен %d, а значение соответствующего аргумента имело тип float. Другой распространенной ошибкой является работа с классом NSNumber, как будто он является типом содержащегося в нем числа; тип NSNumber — это не число, а объект (%0). Кроме того, могут возникнуть сложности при работе с целыми числами, имеющими и не имеющими знак. К счастью, компилятор помогает программисту, выдавая соответствующие предупреждения.

Структуры языка С не являются объектами, поэтому, для того чтобы увидеть значение структуры с помощью функции NSLog, вы должны как-то раскрыть эту структуру. Обычная структура каркаса Cocoa имеет для этой цели свои удобные функции. Например:

NSLog(@"%0", NSStringFromCGRect(self.window.frame)); // {{0, 0}, (320, 480)}

Пуристы насмехаются над грубой отладкой, но я ее использую очень часто: она удобная, информативная и простая. Иногда этот способ является единственным. В отличие от отладчика, функция NSLog работает при любой конфигурации сборки (Debug или Release) и независимо от того, где выполняется приложение (на симуляторе или на устройстве). Эта функция работает, когда невозможно сделать паузу (из-за проблем с потоками, например). Иногда она работает на другом устройстве, например на тестовом приборе, на котором может выполняться приложение. Тестовый прибор может не иметь консоли, поэтому выдать информацию бывает трудно, но все же это возможно: например, тестовый прибор может подсоединить устройство к компьютеру, и вы увидите журнал регистрации в окне Organizer среды Xcode или в окне инструмента iPhone Configuration Utility.

Не забудьте удалить или закомментировать вызовы функции NSLog перед поставкой своего приложения, потому что вы, наверное, не хотите, чтобы при выполнении программы на устройстве клиента она выводила на экран массу ненужной информации. Есть один полезный трюк (позаимствованный у Дженса Альфке (Jens Alfke)) — вызвать функцию MyLog вместо функции NSLog и определить функцию MyLog в своем заголовочном файле (и когда наступит момент для прекращения регистрации, изменить значение с 0 на 1):

 

♦define MyLog if(0); else NSLog

 

Полезно знать, что переменная с именем _cmd содержит селектор для текущего метода. Таким образом, с помощью одной инструкции можно выяснить, где вы находитесь:

NSLog(@"Logging %@ in   NSStringFromSelector(_cmd), self);

(Аналогично в языке С инструкция NSLog (0"%s",  FUNCTION ) регистрирует имя

функции.)

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

Простейшая форма операторов контроля ошибок — это функция языка С (на самом деле это макрос), которой передается один аргумент — условие, которое может быть ложным (0) или истинным (любое другое значение). Если условие ложное, ваше приложение испытает сбой, когда поток управления достигнет соответствующей строки, и в журнал регистрации ошибок будет выведено подробное описание. Например, допустим, что мы утверждаем N0, и это условие ложное и ведет к сбою. Когда поток управления достигнет соответствующей строки, возникнет сбой и появится сообщение:

Assertion failed:  (NO),

function -[AppDelegate application:didFinishLaunchingWithOptions:],

file /Users/mattleopard/Desktop/testing/testing/AppDelegate.m, line 20.

Эта информация позволяет нам найти причину ошибки: мы знаем условие оператора контроля ошибок, метод, в котором содержится оператор контроля ошибок, файл, содержащий этот метод и номер строки.

Операторы контроля ошибок верхнего уровня находятся в макросах NSAssert (используются в методах языка Objective-C) и NSCAssert (используются в функциях языка С). Это позволяет формировать собственные сообщения об ошибках, которые появляются на консоли в дополнение к обычным сообщениям операторов контроля ошибок. Сообщение об ошибках может представлять собой строку форматирования, содержащую спецификаторы формата и соответствующие значения, как в методе NSLog.

Некоторые разработчики полагают, что операторы контроля ошибок должны допускать выполнение оставшегося кода, а не прекращать работу приложения. Однако по умолчанию высокоуровневые макросы NSAssert и NSCAssert в сборке Release недоступны из-за настройки сборки Enable Foundation Assertions, которая имеет значение No для конфигурации Release в шаблонных проектах. Для того чтобы сохранить работоспособные операторы контроля ошибок в сборке Release, это значение в настройках целевого приложения следует изменить на Yes.


 

 

 

Добавить комментарий