Независимо от того, пытаетесь ли вы выяснить, почему в вашем массиве 3 объекта вместо 5 или почему ваша игра играет в обратном направлении с тех пор, как новый парень начал, отладка является важной частью процесса разработки. В конце этой статьи вы получите представление о наиболее важных доступных для вас средствах отладки и о том, как их использовать, чтобы быстрее устранять ошибки.
Мы расскажем, как:
- Проверьте состояние ваших приложений с помощью консоли
- Выполните регистрацию и выйдите за пределы NSLog
- Отслеживайте использование памяти, следуя жизненным циклам объекта
Проверка с помощью консоли
Этот маленький черный ящик внизу XCode должен быть вашим лучшим другом, когда дело доходит до отладки. Он выводит сообщения журнала, сообщения об ошибках и всякие другие полезные вещи, которые помогут вам отследить ошибки. В дополнение к чтению вывода непосредственно из журнала, мы также можем остановиться в определенной точке нашей программы и проверить различные части нашего приложения.
Условно
Я собираюсь предположить, что вы знаете, как работают точки останова (и, если вы этого не сделаете, не беспокойтесь, вы подниметесь к концу этого!). Точки останова имеют неоценимое значение для наблюдения за тем, где находится наше приложение в данный момент времени, но может возникнуть боль при переходе через цикл или рекурсивную функцию после запуска точки останова, пока наш объект не будет равен определенному значению. Введите условные контрольные точки!
Условные точки останова — это точки останова, которые ломаются только при выполнении определенного условия. Представьте, что мы хотим разрываться, только когда объект находится в определенном состоянии или на n-й итерации цикла. Добавьте точку останова к своему коду, щелкнув «желоб» редактора Xcode, щелкните правой кнопкой мыши точку останова и выберите «редактировать точку останова», чтобы задать особые условия.
Вы можете указать условие (например, i == 12) или количество раз, когда точка останова должна игнорироваться. Вы также можете добавить действия, которые происходят автоматически после перерыва, например, команду отладчика, которая печатает значение.
Еще один важный трюк для точки останова — добавление «точки останова исключения». Вы когда-нибудь замечали, что в 99% случаев, когда мы сталкиваемся с исключением, Xcode переносит нас в пул авто-релизов в нашем основном методе?
Установив точку останова исключения, вы можете перейти к точной строке кода, которая вызвала исключение, с точкой останова. Для этого откройте вкладку точки останова исключений (команда + 6). В левом нижнем углу окна есть кнопка «+». Выберите это, чтобы добавить «точку останова исключения». Теперь, когда XCode встречает исключение, оно ломается, где в коде это произошло.
Печать вручную с консоли
Если мы сломали определенную точку в нашем приложении, вообще говоря, это потому, что мы хотим видеть, в каком состоянии находятся наши объекты. Xcode предоставляет нам «представление переменных», то есть это представление внизу Xcode рядом с консолью. Теоретически он отображает текущее состояние всех значений, соответствующих текущему контексту. На практике это иногда оказывается немного глючным. Иногда он не будет перечислять значения или не обновлять их при переходе.
К счастью, мы можем сами проверять конкретные объекты, используя некоторые очень полезные консольные команды. Ввод ‘po’ в консоли позволяет нам получить мгновенную информацию о данном объекте (при работе со скалярными значениями мы используем ‘p’).
Это может быть полезно для просмотра, если объект уже существует (если не будет), будет выводить ноль , определения значения объекта, выяснения того, что массив / словарь содержит во время выполнения, и даже сравнения двух объектов. Поскольку эта команда печатает адрес памяти соответствующего объекта, вы можете распечатать два объекта, которые, по вашему мнению, должны быть одинаковыми, и посмотреть, имеют ли они одинаковый адрес памяти, чтобы быть уверенными.
Еще одна полезная, но скрытая команда, которую вы можете использовать для простой проверки ваших представлений, — это команда recursiveDescription . Вызовите это для представления, чтобы получить распечатку из его иерархии представления.
Эффективное ведение журнала
Есть определенные моменты при отладке нашей программы, мы хотим записать определенное сообщение на консоль. Функция «NSLog» позволяет нам печатать любой вывод, который мы хотим, на консоль. Это может быть важно, если мы хотим следовать определенным путям через наше приложение или проверять, каково значение, без необходимости явно ставить точки останова на каждой возможной строке. NSLog следует тому же формату, что и метод [NSString StringWithFormat] (как вы можете видеть на ярлыке ниже).
Умничать с NSLog
В то время как NSLog полезен, мы должны быть умными в том, как мы его реализуем. Все, что распечатывается из NSLog, попадает в производственный код и поэтому доступно каждому. Если кто-то должен был подключить устройство к органайзеру и посмотреть на консоль, он мог видеть каждое сообщение журнала. Как вы можете себе представить, это может иметь серьезные последствия! Представьте, что вы распечатали какую-то секретную логику алгоритма или пароль пользователя на консоли! Из-за этого приложения иногда отклоняются, если Apple обнаруживает слишком большой вывод на консоль в производственной сборке.
К счастью, есть лучший способ ведения журнала. В зависимости от того, сколько усилий вы хотите приложить, есть несколько способов сделать это. Возможно, самый простой способ — использовать макрос, включающий только NSLog в отладочных сборках. Включение этого в глобально доступный заголовочный файл означает, что вы можете поместить в код столько журналов, сколько захотите, или ни один из них не войдет в работу (при условии, что вы не изменили значения макросов препроцессора по умолчанию, и если вы не знаете, что это, не волнуйтесь).
1
2
3
4
|
#ifdef DEBUG
#define DMLog(…) NSLog(@»%s %@», __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
#define DMLog(…) do { } while (0)
|
Теперь, если вы используете DMLog (или как вы его называете своим), он будет распечатывать его только во время отладочной сборки. Любые производственные сборки ничего не сделают. __PRETTY_FUNCTION__ также помогает, печатая имя функции, из которой поступает запись в журнал.
Делать следующий шаг
Хотя NSLog великолепен, он имеет ряд ограничений:
- Он печатает только локально
- Вы не можете дать журналу «уровень». (Например, критическое, предупреждение, все и т. Д.)
- NSLog работает медленно. Это может значительно замедлить вашу программу при выполнении большого объема обработки
Для тех, кто хочет получить хардкор о ведении журналов, существуют платформы, которые преодолевают некоторые или все эти ограничения в зависимости от того, сколько усилий вы хотите приложить. Я рекомендую взглянуть на следующие инструменты:
- Cocoa LumberJack — одна из известных и универсальных каркасов каркасов для какао. Немного кривой обучения, но это очень мощный
- SNLog — капля замены для NSLog
Следующие жизненные циклы объекта
Хотя внедрение автоматического подсчета ссылок (ARC) гарантировало, что управление памятью не является массовым временным вампиром, каким оно было раньше, все равно важно отслеживать важные события в жизненных циклах нашего объекта. В конце концов, ARC не устраняет возможность утечек памяти или попыток доступа к освобожденному объекту (это просто делает это труднее). С этой целью мы можем реализовать ряд процессов и инструментов, которые помогут нам следить за тем, что делают наши объекты.
Регистрация важных событий
Двумя наиболее важными методами в жизненном цикле объекта Objective-C являются методы init и dealloc . Это хорошая идея записать эти события на вашу консоль, чтобы вы могли наблюдать, когда ваши объекты оживают, и, что более важно, убедиться, что они ушли, когда они должны.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
— (id)init
{
self = [super init];
if (self)
{
NSLog(@»%@: %@», NSStringFromSelector(_cmd), self);
}
return self;
}
— (void)dealloc
{
NSLog(@»%@: %@», NSStringFromSelector(_cmd), self);
}
|
Хотя ввод этого кода может показаться утомительным для начала, есть способы автоматизировать процесс и упростить его. Я могу гарантировать, что это пригодится, когда ваше приложение будет работать так, как не должно. Вы также можете использовать несколько уловок, которые вы узнали в разделе ведения журнала, так что это не распечатывается в производственной сборке (или, что еще лучше, создайте для него макрос самостоятельно!).
Статический анализатор и инспектор
Есть два инструмента, которые идут с XCode, который мы можем использовать, чтобы очистить наш код и сделать наш код менее подверженным ошибкам. Инструмент Static Analyzer — отличный способ для Xcode рекомендовать улучшения нашего кода, от неиспользуемых объектов до потенциально недооцененных или чрезмерно освобожденных объектов (все еще проблема в ARC для объектов Core Foundation). Чтобы увидеть эти рекомендации, перейдите к продукту и выберите «Anlayze».
Инспектор — это мощный инструмент, который позволяет нам тщательно «проверять» различные аспекты нашего приложения, связанные с использованием памяти, работой с файловой системой, и даже обеспечивает способы автоматизации взаимодействия с пользовательским интерфейсом. Для «проверки» приложения выберите «Профиль» в раскрывающемся меню «Продукт».
Откроется окно инструментов, где вы можете выбрать шаблон профиля для запуска. Наиболее распространенными из них являются зомби (мы обсудим это позже), монитор активности и утечки. Утечки, пожалуй, самый полезный шаблон для запуска, чтобы выявлять любые утечки памяти, которые могут присутствовать в вашем приложении.
Зомби твой друг
Хотя гораздо сложнее столкнуться с ужасной ошибкой EXC_BAD_ACCESS сейчас, когда установлена ARC, это все же может произойти при определенных обстоятельствах. Имея дело с UIPopoverController или базовыми базовыми объектами, мы все равно можем попытаться получить доступ к более освобожденному объекту. Обычно, когда мы выпускаем объект в память, он исчезает навсегда. Однако, когда зомби включены, объект помечается только как освобожденный, но остается в памяти. Таким образом, когда мы получаем доступ к объекту Zombie, Xcode может сообщить нам, что вы пытались получить доступ к объекту, которого обычно там не было. Поскольку он все еще знает, что это такое, он может сообщить вам, где и когда это произошло.
Вы можете выследить зомби двумя способами. Либо с помощью инспектора и запуска шаблона профиля Zombie, либо путем включения его в качестве диагностического параметра в параметре сборки «Выполнить». Рядом с кнопкой «Стоп» щелкните имя схемы, затем нажмите «Редактировать схему», а при запуске нажмите вкладку диагностики и выберите «Включить объекты-зомби». Обратите внимание, что отладка в режиме Zombie доступна только при отладке в симуляторе, вы не можете сделать это на реальном устройстве.
Вывод
Надеемся, что вышеизложенное дало вам несколько советов о том, как более эффективно отлаживать ваши приложения. Все дело в том, чтобы найти способы сократить время, затрачиваемое на исправление ошибок, чтобы мы могли тратить больше времени на то, что важно, на создание отличных приложений!
Это далеко не полный список. Существует много других методов, которые здесь не обсуждались, таких как проблемы отладки в производственной среде, удаленные отчеты об ошибках, отчеты о сбоях и многое другое. У вас есть техника, которой вы хотите поделиться? Может быть, у вас есть вопрос, связанный с одним из вышеуказанных пунктов? Отправьте это ниже в комментариях!
Удачного программирования!