10

可能重复:
在Objective-C中拦截方法调用
如何记录iOS应用程序中使用的所有方法

例如,UIViewControlleriOS 中的对象在其视图显示给用户之前会收到许多消息:

  1. viewWillAppear
  2. viewWillLayoutSubviews
  3. viewDidLayoutSubviews
  4. viewDidAppear
  5. ...

因为框架的源代码是不可见的,所以我们不得不依赖书籍或博客,或者有没有办法打印或监视所有通过(1)Objective-C 或(2)任何工具发送到该对象的消息?

4

2 回答 2

17

我使用(并且仍在使用)的最佳方法不是我的评论,而是调用:

(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

注意:自从我上次使用这种方法以来已经有一段时间了,看起来这种方法没有记录私有方法的子类。因此,如果您有一个DummyClasswith-(void)_dummyMethod作为私有然后有一个DummySubClasswith-(void)_dummyMethod实现,则不会记录该消息。

对于 iOS,这仅适用于模拟器。

于 2012-05-25T07:37:43.743 回答
14

您可以使用 DTrace 监视正在运行的应用程序以查看调用的方法和类。您可以在命令行上使用 DTrace 轻松监控在模拟器中运行的 iOS 应用程序,首先您需要找到应用程序的 PID,ps然后您可以运行 DTrace 探针,如下所示:

sudo dtrace -q -n 'objc1234:::entry { printf("%s %s\n", probemod, probefunc); }' 

其中 1234 是应用程序的进程 ID。

这将产生如下所示的输出:

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 deallocs:

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 非常强大,可以做的比我在这里展示的要多得多。

于 2012-05-25T06:53:03.410 回答