
我想通过JRSwizzle来对UIViewController的一些生命周期的方法进行时间统计.
代码如下:
[self jr_swizzleMethod:@selector(viewDidLoad) withMethod:@selector(ri_viewDidLoad) error:nil]; - (void)ri_viewDidLoad { NSDate *start = [NSDate date]; [self ri_viewDidLoad]; NSDate *end = [NSDate date]; NSTimeInterval elapsed = [end timeIntervalSinceDate:start]; NSLog(@"Elapsed:%f(s)",elapsed); } 可是我在 view controller 的- viewDidLoad方法中执行 sleep(), 是采集不到这个时间的, 请问这里有什么问题吗?
谢谢各位, 现在贴出一些代码, 请大家看看有什么问题
Category 类:
@interface UIViewController (ActivityTrace)
+ (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self jr_swizzleMethod:@selector(viewDidLoad) withMethod:@selector(ri_viewDidLoad) error:nil]; [self jr_swizzleMethod:@selector(viewDidAppear:) withMethod:@selector(ri_viewDidAppear:) error:nil]; [self jr_swizzleMethod:@selector(viewDidDisappear:) withMethod:@selector(ri_viewDidDisappear:) error:nil]; }); } #pragma mark - Swizzled method - (void)ri_viewDidLoad { NSDate *start = [NSDate date]; [self ri_viewDidLoad]; NSDate *end = [NSDate date]; NSTimeInterval elapsed = [end timeIntervalSinceDate:start]; NSLog(@"Elapsed:%f(s)",elapsed); if (!kIsRichAPMVIPUser || [[self class] _isClassNotTrackable:[self class]]) { return; } } ... 省略 某个 ViewController.m
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //! sleep 的这个值不会影响到 ri_viewDidLoad sleep(2); } 1 randm 2016-02-25 12:49:58 +08:00 你要用 ri_viewDidLoad |
nbsp; 2 xieweizhi007 OP @randm 这里是没问题的, 用 ri_viewDidLoad 就会死循环啦. 因为 ri_viewDidLoad 里面调用的 ri_viewDidLoad 其实是原来的 viewDidLoad 方法. |
3 zhicheng 2016-02-25 16:02:32 +08:00 1. 你想统计时间,这和 MethodSwizzling 有什么关系? 2. 你 Swizzling viewDidLoad 有什么用? |
4 xieweizhi007 OP @zhicheng , 我是想通过这种方法来统计所有 Controller 的生命周期的运行效率. |
5 chmlai 2016-02-25 16:33:02 +08:00 代码看起来没有错, 分别在 ri_viewDidLoad 和 viewDidiLoad 里面 Log 一下看看 |
6 xieweizhi007 OP @chmlai 原始的 viewDidLoad 也不需要 log 的, sleep 之后确实会卡顿. 而 ri_viewDidLoad 方法却是不正确的. |
7 LINAICAI 2016-02-25 17:21:48 +08:00 [self ri_viewDidLoad]; 这不对吧,不是应该[super ri_viewDidLoad];?? |
8 juxingzhutou 2016-02-25 18:57:42 +08:00 你的 jr_swizzleMethod 是在哪里调用的?我觉得问题可能在 swizzling 的次数上。 贴上更完整的代码有利于大家判断。 |
9 juxingzhutou 2016-02-25 18:58:30 +08:00 @LINAICAI method swizzling 就是调用自身 selector 来调用原版方法的。 |
10 tedzhou 2016-02-25 19:06:37 +08:00 是不是有其他信号相关的代码把线程唤醒了? |
11 xieweizhi007 OP @juxingzhutou 是的是的. |
12 xieweizhi007 OP @tedzhou 没有, 你可以看看. |
13 tedzhou 2016-02-25 20:02:30 +08:00 swizzle 不能把 subClass 的方法也交换的哦 |
14 juxingzhutou 2016-02-25 20:07:57 +08:00 13 楼说得对,我再补充解释一下。你的代码的问题是这样的,实际上你 swizzling 的方法是子类中的`[super viewDidLoad]`这个方法。 也就是说 sleep 是在你的 ri_viewDidLoad 方法执行完之后才执行的,`[super viewDidLoad]`执行的才是 ri_viewDidLoad 方法。 |
15 xieweizhi007 OP |
16 wezzard 2016-02-26 14:14:30 +08:00 我建你描所有 classes 然後找到目做 is-a swizzle ,做一 wrapper wrap 住所有要的 class ,控制住所有消息送。但是就是肯定影性能。 |
17 xieweizhi007 OP @wezzard 我目前就是这样做的, 是有性能影响 |
18 Python666666 2017-02-08 10:32:20 +08:00 @xieweizhi007 可以分享一下你的解决方案吗 |
19 xieweizhi007 OP @Python666666 跟 @wezzard 说的方案一样 |
20 Python666666 2017-02-14 15:16:56 +08:00 @wezzard 不是很懂,可以分享一下 Demo 吗, [email protected],感恩 |
21 xieweizhi007 OP @Python666666 你可以参考这个开源项目是怎样 hook 所有 HTTP 网络请求的 https://github.com/Flipboard/FLEX |
22 Python666666 2017-02-20 10:57:14 +08:00 @xieweizhi007 谢谢 遍历所有类,去除不是工程内的,再全部添加 hook 就可以了 |