Можно ли отслеживать или распечатывать сообщения, отправленные объекту в Objective-C?
Возможный дубликат:
Вызов метода перехвата в Objective-C
Как регистрировать все методы, используемые в приложении iOS
Например, объект UIViewController
в iOS получает много сообщений, прежде чем его представление будет показано пользователю:
-
viewWillAppear
-
viewWillLayoutSubviews
-
viewDidLayoutSubviews
-
viewDidAppear
- ...
потому что исходный код рамки не доступен для просмотра, мы должны полагаться на книги или блоги, или есть способ распечатать или контролировать все сообщения, отправленные этому объекту, с помощью (1) Objective-C или (2) любым инструментом?
Ответы
Ответ 1
Вместо моего комментария лучший подход, который я использовал (и до сих пор использую), вызывает:
(void)instrumentObjcMessageSends(YES);
Когда мне нужно начать регистрировать все сообщения, а затем:
(void)instrumentObjcMessageSends(NO);
Не забудьте добавить #import <objc/runtime.h>
.
Когда мне это больше не нужно. Досадно, что журнал создан под /tmp/msgSends-
, и это означает, что вам нужно открыть терминал и использовать tail
, чтобы увидеть его читаемым способом.
Что печатается, это примерно так:
- CustomTableViewController UIViewController _parentModalViewController
- CustomTableViewController UIViewController isPerformingModalTransition
- CustomTableViewController UIViewController setInAnimatedVCTransition:
- CustomTableViewController UIViewController viewWillMoveToWindow:
- CustomTableViewController UIViewController isPerformingModalTransition
- CustomTableViewController UIViewController parentViewController
- CustomTableViewController UIViewController _popoverController
- CustomTableViewController UIViewController _didSelfOrAncestorBeginAppearanceTransition
- CustomTableViewController UIViewController parentViewController
- CustomTableViewController UIViewController __viewWillDisappear:
- CustomTableViewController UIViewController _setViewAppearState:isAnimating:
- CustomTableViewController UIViewController automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers
Примечание. Прошло некоторое время с тех пор, как я использовал этот подход в последний раз, и похоже, что этот подход не регистрирует приватные методы подкласса. Итак, если у вас есть DummyClass
с -(void)_dummyMethod
как закрытый, а затем DummySubClass
с реализацией -(void)_dummyMethod
, сообщение не будет регистрироваться.
Для iOS это работает только на Simulator.
Ответ 2
Вы можете использовать DTrace для мониторинга запущенного приложения, чтобы увидеть методы и вызываемые классы. Вы можете легко контролировать приложение iOS, работающее в Simulator, используя DTrace в командной строке. Сначала вам нужно найти PID приложения с помощью ps
, а затем вы можете запустить DTrace-зонд следующим образом:
sudo dtrace -q -n 'objc1234:::entry { printf("%s %s\n", probemod, probefunc); }'
где 1234 - это идентификатор процесса приложения.
Это приведет к выходу, который выглядит следующим образом:
UIStatusBarItemView -isVisible
UIStatusBarLayoutManager -_positionAfterPlacingItemView:startPosition:
UIView(Geometry) -frame
CALayer -frame
UIStatusBarLayoutManager -_startPosition
UIView(Geometry) -bounds
CALayer -bounds
UIStatusBarItemView -standardPadding
UIStatusBarItem -appearsOnLeft
UIStatusBarItem -leftOrder
Если вы заинтересованы только в отслеживании одного класса, например, UIView
, вы можете использовать:
sudo dtrace -q -n 'objc1234:UIView::entry { printf("%s %s\n", probemod, probefunc); }'
Если вы хотите трассировать все вызовы на dealloc
для всех классов, вы должны использовать:
sudo dtrace -q -n 'objc1234::-dealloc:entry { printf("%s %s\n", probemod, probefunc); }'
Очевидно, вы могли бы объединить их, чтобы увидеть только UIView
dealloc
s:
sudo dtrace -q -n 'objc1234:UIView:-dealloc:entry { printf("%s %s\n", probemod, probefunc); }'
Если вы хотите различать конкретный объект класса, вы также можете распечатать адрес памяти объекта (self
), используя следующее:
sudo dtrace -q -n 'objc1234:UIView:-dealloc:entry { printf("%s (0x%p) %s\n", probemod, arg0, probefunc); }'
DTrace чрезвычайно эффективен и может делать значительно больше, чем показано здесь.