Как регистрировать все методы, используемые в приложении iOS
Я занимаюсь разработкой iPad-приложения для клиента. Там уже проделана значительная работа, и я пытаюсь объединить все, что предназначено для запуска.
Одна из вещей, которые я хотел бы сделать, - это журнал, который вызывает вызовы при запуске приложения. Я видел пользовательский DTrace script, который предназначен для регистрации всех методов при запуске, но когда я запускаю его в Инструментах, я не получаю никаких результатов.
Каков наилучший способ регистрации методов?
Ответы
Ответ 1
Вдохновленный tc ответом на аналогичный вопрос здесь, я собрал действие точки останова отладки, которое выведет имя класса и метода за каждый раз, когда objc_msgSend() будет запускается в вашем приложении. Это работает аналогично DTrace script, описанному в этом ответе.
Чтобы включить это действие точки останова, создайте новую символическую точку останова (в 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. Адреса памяти, указанные выше, будут работать только против Simulator, поэтому вам может потребоваться настроить ее для работы с приложениями на устройствах iOS. Коллин предлагает следующую модификацию в его ответе, чтобы запустить это на устройстве:
printf "[%s %s]\n", (char *)object_getClassName($r0),$r1
Кроме того, я думаю, вы увидите, что выключение каждого метода, вызванного в вашем приложении, приведет к переполнению информации. Возможно, вы сможете использовать некоторые условия для фильтрации, но я не знаю, поможет ли это вам узнать, как выполняется ваш код.
Ответ 2
Если вы используете LLDB, вам нужно будет использовать следующие команды отладчика. Они были протестированы в Xcode 4.6.
Device:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($r0),$r1)
Simulator:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)), *(long *)($esp+8))
Ответ 3
Чтобы отследить код приложения под Xcode 6 на устройстве, мне пришлось использовать следующее выражение отладчика.
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($arg1),$arg2)
Ответ 4
Подход Брэда Ларсона может быть адаптирован для работы на устройстве с помощью команды отладчика:
printf "[%s %s]\n", (char *)object_getClassName($r0),$r1
Более подробную информацию можно найти в Технической заметке здесь: technotes
Ответ 5
более поздние версии xcode, которые вы должны вызвать таким образом
expr -- (void)printf("[%s, %s]\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8) )
Ответ 6
Если вы хотите ограничить вывод только сообщениями, отправленными на один класс, вы можете добавить условие, подобное этому
(int) strcmp ((char *) object_getClassName ($ r0), "NSString" ) == 0
Ответ 7
Для приложений 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 --
![]()
Источник ТАК ответ
Ответ 8
Один разработчик научил меня добавлять те же самые два оператора журнала к каждому методу. Первая - первая, вторая - последняя. Я думаю, что у него есть script, который делает это автоматически для своих проектов, но результат:
NSLog(@"<<< Entering %s >>>", __PRETTY_FUNCTION__);
NSLog(@"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
На консоли это выплюнет что-то вроде:
<<< Entering -[MainListTableViewController viewDidLoad] >>>
Очень полезно отслеживать, что происходит.
Ответ 9
Если вы хотите регистрировать методы в Simulator на 64-битной версии, используйте следующую команду:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($rdi), (char *) $rsi)
Или, если это не работает, запишите его так:
![введите описание изображения здесь]()
Основная идея - использовать $rdi для объекта (self) и $rsi для селектора.
Ответ 10
NSLog(@"%@", NSStringFromSelector(_cmd));
ИЛИ
NSLog(@"%s", __PRETTY_FUNCTION__);