Как записать все методы, используемые в приложении iOS - PullRequest
41 голосов
/ 01 сентября 2011

Я занимаюсь разработкой приложения для iPad для клиента.Уже проделана значительная работа, и я пытаюсь собрать воедино, как все это работает.

Одна из вещей, которую я хотел бы сделать, - записывать, какие методы вызываются, когдаприложение работает.Я видел собственный сценарий DTrace, предназначенный для регистрации всех методов при запуске, но когда я запускаю его в Instruments, я не получаю результатов.

Какой лучший способ регистрации методов?

Ответы [ 10 ]

54 голосов
/ 01 сентября 2011

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

Чтобы включить это действие точки останова, создайте новую символическую точку останова (в Xcode 4 перейдите к навигатору точек останова и создайте новыйсимволическая точка останова с использованием плюса в левом нижнем углу окна).Установите символ objc_msgSend, установите его для автоматического продолжения после оценки действий и установите действие в качестве команды отладчика, используя следующее:

printf "[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)),*(long *)($esp+8)

Ваша точка останова должна выглядеть примерно так:

Breakpoint action

Это должно выводить подобные сообщения при запуске с вашим приложением:

[UIApplication sharedApplication]
[UIApplication _isClassic]
[NSCFString getCString:maxLength:encoding:]
[UIApplication class]
[SLSMoleculeAppDelegate isSubclassOfClass:]
[SLSMoleculeAppDelegate initialize]

Если вам интересно, откуда я вытащил адреса памяти, прочитайте эта статья Phrack о внутренних объектах Objective-C.Приведенные выше адреса памяти будут работать только на симуляторе, поэтому вам может потребоваться настроить его для работы с приложениями на устройствах iOS.Коллин предлагает следующую модификацию в своем ответе для запуска этого на устройстве:

printf "[%s %s]\n", (char *)object_getClassName($r0),$r1

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

17 голосов
/ 10 июня 2013

Если вы используете LLDB, вам нужно будет использовать следующие команды отладчика.Они были протестированы в Xcode 4.6.

Устройство:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($r0),$r1)

Симулятор:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)), *(long *)($esp+8))
5 голосов
/ 19 октября 2015

Чтобы отследить код приложения под Xcode 6 на устройстве, мне пришлось использовать следующее выражение отладчика.

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($arg1),$arg2)
4 голосов
/ 09 декабря 2011

Подход Брэда Ларсона может быть адаптирован для запуска на устройстве с помощью команды отладчика:

printf "[%s %s]\n", (char *)object_getClassName($r0),$r1

Более подробную информацию можно найти в Техническом примечании здесь: technotes

3 голосов
/ 02 января 2013

более поздние версии xcode, которые вам нужно так называть

expr -- (void)printf("[%s, %s]\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8) )
2 голосов
/ 04 февраля 2014

Если вы хотите ограничить вывод только сообщениями, отправленными одному классу, вы можете добавить условие вроде этого

(int) strcmp ((char *) object_getClassName ($ r0), "NSString") == 0

1 голос
/ 17 февраля 2017

Если вы хотите регистрировать методы в симуляторе на 64-битной системе, используйте следующую команду:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($rdi), (char *) $rsi)

Или, если это не сработает, запишите это так:

enter image description here

Основная идея - использовать $ rdi для объекта (self) и $ rsi для селектора.

1 голос
/ 01 сентября 2011

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

NSLog(@"<<< Entering %s >>>", __PRETTY_FUNCTION__);
NSLog(@"<<< Leaving %s >>>", __PRETTY_FUNCTION__);

На консоли это выдаст что-то вроде:

 <<< Entering -[MainListTableViewController viewDidLoad] >>>

Очень полезнов отслеживании того, что происходит.

0 голосов
/ 29 марта 2019

Для iOS simulator приложений, которые запускаются как процессы архитектуры arm / x86_64 на Mac

Создание Symbolic Breakpoint с objc_msgSend символом и следующим Debugger Command

p (void)printf("[%s, %s]\n", (char*)object_getClassName($arg1), $arg2)

p является псевдонимом для expr --

enter image description here

Источник SO ответ

0 голосов
/ 09 мая 2016
NSLog(@"%@", NSStringFromSelector(_cmd));

OR

NSLog(@"%s", __PRETTY_FUNCTION__);
...