我想通过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
|
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 1
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 就可以了
|