Трюки с NSLog
В мои первые дни разработки для iOS, я был вынужден сразу начать выполнять задачу, осматриваясь и осваиваясь попутно. Это хороший метод. Но можно пропустить что-то простое. Когда приложение аварийно завершилось, я не мог понять, по какой причине.
Помимо отладчика в XCode есть еще консоль (Console). Вызывается она из меню Run → Console. Или комбинацией Cmd + Shift + R. Если что-то сломалось, там можно найти сообщение об этом. Сообщения в консоль могут добавляться автоматически, например, если пытаться сделать лишний autorelease, консоль отразит этот момент. А могут добавляться и разработчиком. Делается это с помощью NSLog. Рекомендую принять к сведению и использовать.
Если приложение завершило работу аварийно, можно обратиться к iPhone Crash Reporter и посмотреть отчет в виде списка свойств в файле .crash по адресу /Library/Logs/CrashReporter.
Слышал, как ругают NSLog за избыточность. Возможно, не сразу встретятся такие случаи, чтобы можно было по достоинству оценить NSLog. Но кому-то уже встретились.
Формат NSLog будет знаком всем, кто работал с printf(). Идея точно такая же: строка, определяющая формат и порядок вывода аргументов, а затем сами аргументы. В общем, это можно назвать printf() для NS и UI объектов. NSLog автоматически добавляет дату и время к выводу. Спецификатор %@ служит для вывода объекта. Большинство спецификаторов аналогичны тем, что используются в printf(). При вызове NSLog просто вызывает NSLogv, сообщая переменное число параметров.
NSLog(@"String: %@ ", aString); NSLog(@"Float: %f ", aFloat); NSLog(@"Integer: %i ", aInt);
Следующий код выводит имя файла, номер строки и имя функции. В C++ __FUNCTION__ показывает искаженное имя, в отличие от __PRETTY_FUNCTION__. В Cocoa между ними нет разницы.
NSLog(@"%s %d %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
Этот код можно несколько расширить. DLog будет использоваться только если установлена переменная DEBUG. ALog же всегда будет выводить текст, как и обычный NSLog.
#ifdef DEBUG #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else #define DLog(...) #endif #define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Например, ALog(@"Hello world") даст следующий результат.
-[LibraryController awakeFromNib] [Line 364] Hello world
Чтобы выключить логи по всей программе, можно прибегнуть к простому макросу.
#define NSLog
- Колдунства по NSLog взяты из дискуссии на Stack Overflow
- Еще немного про NSLog можно прочесть на CocoaDev
- Полный список спецификаторов из документации Apple
- Документация по NSLogv
Ваш комментарий