请教一个 Swizzle method 的问题. - V2EX
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 年 2 月 8 日 4842 次点击
    这是一个创建于 3362 天前的主题,其中的信息可能已经有所发展或是发生改变。

    t/259024#reply18

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

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

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

    5 条回复    2017-02-10 10:06:40 +08:00
    kitalphaj
        1
    kitalphaj  
       2017 年 2 月 8 日
    他的意思应该是说你在启动的时候,扫描所有 classe (`objc_getClassList ` ), 然后每个 class 都看看是不是 view controller 的子类,如果是的话就把它的 viewDidLoad 换成带时间统计的 my_viewDidLoad 。(而不仅仅是换 UIViewController 这个具体类的 viewDidLoad 方法)。
    Python666666
        2
    Python666666  
    OP
       2017 年 2 月 8 日
    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 年 2 月 8 日
    @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 年 2 月 8 日
    @Python666666 为啥达不到,你相当于是把所有的实现都改了,那不就是所有时间都能统计了么。所以你到底想要实现什么?
    xieweizhi007
        5
    xieweizhi007  
       2017 年 2 月 10 日
    @Python666666 , 就是 @kitalphaj 这么说做的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3035 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 51ms UTC 07:19 PVG 15:19 LAX 00:19 JFK 03:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86