请教一个 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
xieweizhi007
V2EX    iDev

请教一个 Swizzle method 的问题.

  •  
  •   xieweizhi007 2016-02-25 12:39:00 +08:00 4391 次点击
    这是一个创建于 3552 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想通过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(), 是采集不到这个时间的, 请问这里有什么问题吗?

    第 1 条附言    2016-02-25 19:18:17 +08:00

    谢谢各位, 现在贴出一些代码, 请大家看看有什么问题

    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); } 
    第 2 条附言    2016-02-26 14:48:12 +08:00
    目前的做法的跟 @wezzard 说的差不多, 缺点就是会影响性能并且比较复杂.
    22 条回复    2017-02-20 10:57:14 +08:00
    randm
        1
    randm  
       2016-02-25 12:49:58 +08:00
    你要用 ri_viewDidLoad
    xieweizhi007
    nbsp;   2
    xieweizhi007  
    OP
       2016-02-25 14:39:27 +08:00
    @randm 这里是没问题的, 用 ri_viewDidLoad 就会死循环啦. 因为 ri_viewDidLoad 里面调用的 ri_viewDidLoad 其实是原来的 viewDidLoad 方法.
    zhicheng
        3
    zhicheng  
       2016-02-25 16:02:32 +08:00
    1. 你想统计时间,这和 MethodSwizzling 有什么关系?
    2. 你 Swizzling viewDidLoad 有什么用?
    xieweizhi007
        4
    xieweizhi007  
    OP
       2016-02-25 16:20:11 +08:00
    @zhicheng , 我是想通过这种方法来统计所有 Controller 的生命周期的运行效率.
    chmlai
        5
    chmlai  
       2016-02-25 16:33:02 +08:00
    代码看起来没有错, 分别在 ri_viewDidLoad 和 viewDidiLoad 里面 Log 一下看看
    xieweizhi007
        6
    xieweizhi007  
    OP
       2016-02-25 16:54:55 +08:00
    @chmlai 原始的 viewDidLoad 也不需要 log 的, sleep 之后确实会卡顿. 而 ri_viewDidLoad 方法却是不正确的.
    LINAICAI
        7
    LINAICAI  
       2016-02-25 17:21:48 +08:00
    [self ri_viewDidLoad];
    这不对吧,不是应该[super ri_viewDidLoad];??
    juxingzhutou
        8
    juxingzhutou  
       2016-02-25 18:57:42 +08:00
    你的 jr_swizzleMethod 是在哪里调用的?我觉得问题可能在 swizzling 的次数上。

    贴上更完整的代码有利于大家判断。
    juxingzhutou
        9
    juxingzhutou  
       2016-02-25 18:58:30 +08:00
    @LINAICAI method swizzling 就是调用自身 selector 来调用原版方法的。
    tedzhou
        10
    tedzhou  
       2016-02-25 19:06:37 +08:00
    是不是有其他信号相关的代码把线程唤醒了?
    xieweizhi007
        11
    xieweizhi007  
    OP
       2016-02-25 19:18:48 +08:00
    @juxingzhutou 是的是的.
    xieweizhi007
        12
    xieweizhi007  
    OP
       2016-02-25 19:19:03 +08:00
    @tedzhou 没有, 你可以看看.
    tedzhou
        13
    tedzhou  
       2016-02-25 20:02:30 +08:00
    swizzle 不能把 subClass 的方法也交换的哦
    juxingzhutou
        14
    juxingzhutou  
       2016-02-25 20:07:57 +08:00   1
    13 楼说得对,我再补充解释一下。你的代码的问题是这样的,实际上你 swizzling 的方法是子类中的`[super viewDidLoad]`这个方法。

    也就是说 sleep 是在你的 ri_viewDidLoad 方法执行完之后才执行的,`[super viewDidLoad]`执行的才是 ri_viewDidLoad 方法。
    xieweizhi007
        15
    xieweizhi007  
    OP
       2016-02-26 09:18:45 +08:00
    @tedzhou
    @juxingzhutou

    我大概懂了, 谢谢 ^ ^
    wezzard
        16
    wezzard  
       2016-02-26 14:14:30 +08:00
    我建你描所有 classes 然後找到目做 is-a swizzle ,做一 wrapper wrap 住所有要的 class ,控制住所有消息送。但是就是肯定影性能。
        17
    xieweizhi007  
    OP
       2016-02-26 14:47:06 +08:00
    @wezzard 我目前就是这样做的, 是有性能影响
    Python666666
        18
    Python666666  
       2017-02-08 10:32:20 +08:00
    @xieweizhi007 可以分享一下你的解决方案吗
    xieweizhi007
        19
    xieweizhi007  
    OP
       2017-02-08 19:23:15 +08:00
    @Python666666 跟 @wezzard 说的方案一样
    Python666666
        20
    Python666666  
       2017-02-14 15:16:56 +08:00
    @wezzard 不是很懂,可以分享一下 Demo 吗, [email protected],感恩
    xieweizhi007
        21
    xieweizhi007  
    OP
       2017-02-14 22:29:20 +08:00
    @Python666666 你可以参考这个开源项目是怎样 hook 所有 HTTP 网络请求的 https://github.com/Flipboard/FLEX
    Python666666
        22
    Python666666  
       2017-02-20 10:57:14 +08:00
    @xieweizhi007 谢谢 遍历所有类,去除不是工程内的,再全部添加 hook 就可以了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1334 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 16:39 PVG 00:39 LAX 08:39 JFK 11:39
    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