请教一个 Swizzle method 的问题.

2017-02-08 17:30:30 +08:00
 Python666666

https://www.v2ex.com/t/259024#reply18

这个帖子是具体的内容,直接交互的 2 个方法并不能统计到子的方法运行时间,只能统计到父的

评论中有这么一句回复: 我建議你啓動時掃描所有 classes 然後找到目標做 is-a swizzle ,做一個 wrapper wrap 住所有要統計的 class ,控制住所有消息發送。但是就是肯定會影響性能。

请教一下这个具体的实现是怎么样的呢?

4030 次点击
所在节点    iDev
5 条回复
kitalphaj
2017-02-08 18:00:58 +08:00
他的意思应该是说你在启动的时候,扫描所有 classe (`objc_getClassList ` ), 然后每个 class 都看看是不是 view controller 的子类,如果是的话就把它的 viewDidLoad 换成带时间统计的 my_viewDidLoad 。(而不仅仅是换 UIViewController 这个具体类的 viewDidLoad 方法)。
Python666666
2017-02-08 18:09:12 +08:00
void -[_priv_NBSUIHookMatrix nbs_jump_viewDidLoad:superClass:](void * self, void * _cmd, void * * arg2, void * arg3) {
rbx = arg3;
var_60 = arg2;
r15 = _cmd;
r14 = self;
rax = [self class];
rax = class_getSuperclass(rax);
if ((rbx != 0x0) && (rax != rbx)) {
rax = var_60;
if (rax != 0x0) {
rdi = r14;
(rax)(rdi, @selector(viewDidLoad));
}
else {
NSLog(@"");
[[r14 super] viewDidLoad];
}
}
else {
var_58 = r15;
var_A8 = _currentViewController;
r13 = *_currentViewController;
if (r13 == 0x0) {
rax = [_priv_NBSLensControllerReplacer alloc];
rax = [rax init];
rdi = *_currentViewController;
*_currentViewController = rax;
[rdi release];
r13 = *_currentViewController;
}
rbx = [[NSString stringWithFormat:@"%@", [r14 class]] retain];
rdi = r13;
r13 = r14;
[rdi setControllerName:rbx];
rdi = rbx;
rbx = 0x0;
[rdi release];
[*_currentViewController setVc_address:r13];
rdx = @"%d#loading";
rcx = r13;
r12 = [[NSString stringWithFormat:rdx] retain];
if (r13 != 0x0) {
rcx = class_getName([r13 class]);
rbx = [[NSString stringWithFormat:@"MobileView/Controller/%s#%@", rcx, r8] retain];
}
var_88 = rbx;
r14 = [[_priv_NBSUILogCenter_assistant alloc] initWithControllerName:rbx, rcx, 0x0];
var_70 = r14;
[r14 setVC_Address:_objc_release, rcx, 0x0];
[r14 setIsOther:0x0, rcx, 0x0];
[*_controllerStack push:r14, rcx, 0x0];
rbx = [_nbs_glb_all_activing_VCS() retain];
rcx = r12;
var_90 = r12;
[rbx setObject:r14 forKey:rcx, 0x0];
[rbx release];
rbx = [[NSDate date] retain];
[rbx timeIntervalSince1970];
xmm0 = intrinsic_mulsd(xmm0, *0x100086028);
r12 = intrinsic_cvttsd2si(r12, xmm0);
[rbx release];
[r14 setStartTime:r12, rcx, 0x0];
var_48 = _objc_release;
r13 = [[NSString stringWithFormat:@"%s", class_getName([_objc_release class])] retain];
rbx = [NSStringFromSelector(var_58) retain];
r8 = *_currentViewController;
rdx = r13;
rcx = rbx;
var_78 = [_nbs_embedIn_start() retain];
[rbx release];
[r13 release];
rbx = [[_priv_NBSLensInterfaceEventLogger shareObject] retain];
var_68 = rbx;
r13 = [_priv_NBSLensUITraceSegment new];
var_50 = r13;
rbx = [[rbx theStack] retain];
[rbx push:r13, rcx, r8];
[rbx release];
r14 = [[NSString stringWithFormat:@"%s", class_getName([_objc_release class])] retain];
r15 = [NSStringFromSelector(var_58) retain];
rbx = [[NSString stringWithFormat:@"%@#%@", r14, r15] retain];
var_98 = rbx;
rdi = r15;
[rdi release];
[r14 release];
[r13 setSegmentName:rbx];
rax = [NSDictionary dictionary];
rax = [rax retain];
var_A0 = rax;
[r13 setSegmentParam:rax];
rbx = [[NSThread currentThread] retain];
rdx = rbx;
[r13 setThreadInfomation:rdx];
[rbx release];
rbx = [[NSDate date] retain];
[rbx timeIntervalSince1970];
xmm0 = intrinsic_mulsd(xmm0, *0x100086028);
var_58 = intrinsic_movsd(var_58, xmm0);
[rbx release];
xmm0 = intrinsic_movsd(xmm0, var_58);
[r13 setStartTime:rdx];
[r13 setEntryTime:0x0];
r12 = [_priv_NBSLensUITraceSegment new];
var_80 = r12;
xmm0 = intrinsic_movsd(xmm0, var_58);
[r12 setStartTime:0x0];
r14 = [[NSString stringWithFormat:@"%s", class_getName([var_48 class])] retain];
r13 = _objc_release;
rbx = [[NSString stringWithFormat:@"%@#viewLoading", r14] retain];
[r12 setSegmentName:rbx];
[rbx release];
[r14 release];
rcx = var_30;
rbx = [[NSDictionary dictionaryWithObjects:rbx forKeys:rcx count:0x0] retain];
[r12 setSegmentParam:rbx];
[rbx release];
rbx = [[NSThread currentThread] retain];
[r12 setThreadInfomation:rbx];
[rbx release];
[r12 setEntryTime:0x0];
rax = var_60;
if (rax != 0x0) {
rbx = var_48;
(rax)(rbx, @selector(viewDidLoad), 0x0, rcx, 0x0);
}
else {
rbx = var_48;
NSLog(@"");
[[rbx super] viewDidLoad];
}
var_48 = rbx;
_nbs_embedIn_finish();
rdx = [var_78 mach_tm2];
[var_70 setFinishTime:rdx];
rbx = [[NSDate date] retain];
[rbx timeIntervalSince1970];
xmm0 = intrinsic_mulsd(xmm0, *0x100086028);
var_60 = intrinsic_movsd(var_60, xmm0);
(r13)(rbx, @selector(timeIntervalSince1970), rdx);
xmm0 = intrinsic_movsd(xmm0, var_60);
xmm0 = intrinsic_subsd(xmm0, var_58);
[var_50 setExitTime:intrinsic_cvttsd2si(rdx, xmm0)];
rbx = [[var_68 theStack] retain];
rdx = var_50;
[rbx pop:rdx];
[rbx release];
rbx = [[var_68 theStack] retain];
r14 = [rbx isEmpty];
[rbx release];
if (r14 != 0x0) {
rsi = @selector(childSegments);
r14 = @selector(addObject:);
}
else {
r14 = [[var_68 theStack] retain];
r15 = [[r14 peer] retain];
[r14 release];
[r15 startTime];
xmm1 = intrinsic_movsd(xmm1, var_58);
xmm1 = intrinsic_subsd(xmm1, xmm0);
rdx = intrinsic_cvttsd2si(rdx, xmm1);
[var_50 setEntryTime:rdx];
[r15 startTime];
[var_50 setExitTime:intrinsic_cvttsd2si(rdx, intrinsic_subsd(intrinsic_movsd(xmm1, var_60), xmm0))];
r13 = [[r15 childSegments] retain];
r14 = @selector(addObject:);
rdx = var_50;
_objc_msgSend(r13, r14);
[r13 release];
[r15 release];
rsi = @selector(childSegments);
}
rbx = [_objc_msgSend(var_80, rsi, rdx) retain];
_objc_msgSend(rbx, r14, var_50);
[rbx release];
objc_setAssociatedObject(var_48, @"viewLoading", var_80, 0x1);
rax = [*_controllerStack pop];
rax = [rax retain];
[rax release];
rbx = [[_priv_NBSLENS_VCSBuffer sharedObj] retain];
[rbx addObj:var_70];
[rbx release];
rbx = [_nbs_glb_all_activing_VCS() retain];
[rbx removeObjectForKey:var_90];
[rbx release];
[var_80 release];
[var_A0 release];
[var_98 release];
[var_50 release];
[var_68 release];
[var_78 release];
[var_70 release];
[var_88 release];
[var_90 release];
}
return;
}

这个是逆向的看别人实现的,但是看的不是很明白,有人一起来分析一下吗
Python666666
2017-02-08 18:10:08 +08:00
@kitalphaj objc_getClassList 这样的话,启动就扫描了所以的类实现了,好想也达不到这个效果, NSArray *sfl_classGetSubclasses(Class parentClass) {
int numClasses = objc_getClassList(NULL, 0);
Class *classes = NULL;

classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);

NSMutableArray *result = [NSMutableArray array];
for (NSInteger i = 0; i < numClasses; i++) {
Class superClass = classes[i];
do {
superClass = class_getSuperclass(superClass);
} while(superClass && superClass != parentClass);

if (superClass == nil) {
continue;
}

[result addObject:classes[i]];
}
free(classes);
return result;
}
类似这样吗
kitalphaj
2017-02-08 20:18:37 +08:00
@Python666666 为啥达不到,你相当于是把所有的实现都改了,那不就是所有时间都能统计了么。所以你到底想要实现什么?
xieweizhi007
2017-02-10 10:06:40 +08:00
@Python666666 , 就是 @kitalphaj 这么说做的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/339060

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX