Могут ли сообщения, отправленные объекту в Objective-C, отслеживаться или распечатываться?
Возможный дубликат:
Вызов метода перехвата в Objective-C
Как зарегистрировать все методы, используемые в приложении iOS
Например, UIViewController
объект в iOS получает много сообщений, прежде чем его вид будет показан пользователю:
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
- ...
поскольку исходный код фреймворка недоступен для просмотра, мы должны полагаться на книги или блоги или есть способ распечатать или отследить все сообщения, отправленные этому объекту с помощью (1) Objective-C или (2) любым инструментом?
2 ответа
Вместо моего комментария лучший подход, который я использовал (и до сих пор использую), это вызов:
(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 это работает только на симуляторе.
Вы можете использовать DTrace для мониторинга работающего приложения, чтобы увидеть вызываемые методы и классы. Вы можете легко контролировать приложение iOS, запущенное в симуляторе, используя 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 очень мощный и может сделать значительно больше, чем я показал здесь.