V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
Python666666
V2EX  ›  iDev

请教一个 Swizzle method 的问题.

  •  
  •   Python666666 · 2017-02-08 17:30:30 +08:00 · 4155 次点击
    这是一个创建于 2844 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    5 条回复    2017-02-10 10:06:40 +08:00
    kitalphaj
        1
    kitalphaj  
       2017-02-08 18:00:58 +08:00
    他的意思应该是说你在启动的时候,扫描所有 classe (`objc_getClassList ` ), 然后每个 class 都看看是不是 view controller 的子类,如果是的话就把它的 viewDidLoad 换成带时间统计的 my_viewDidLoad 。(而不仅仅是换 UIViewController 这个具体类的 viewDidLoad 方法)。
    Python666666
        2
    Python666666  
    OP
       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
        3
    Python666666  
    OP
       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
        4
    kitalphaj  
       2017-02-08 20:18:37 +08:00
    @Python666666 为啥达不到,你相当于是把所有的实现都改了,那不就是所有时间都能统计了么。所以你到底想要实现什么?
    xieweizhi007
        5
    xieweizhi007  
       2017-02-10 10:06:40 +08:00
    @Python666666 , 就是 @kitalphaj 这么说做的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2786 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:26 · PVG 10:26 · LAX 18:26 · JFK 21:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.