如何高效的准确的获取一个工程所有控制器的 viewdidload 方法的执行时间? - 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
changhogliang
V2EX    iDev

如何高效的准确的获取一个工程所有控制器的 viewdidload 方法的执行时间?

  •  
  •   changhogliang 2017-03-14 15:23:15 +08:00 3283 次点击
    这是一个创建于 3208 天前的主题,其中的信息可能已经有所发展或是发生改变。
    先说说现在的做法,首先在启动时获取 objc_getClassList 获取项目中所有的类,然后看这个类是否有 viewdidload 方法,如果就 swizzle method,然后在替换的方法中间调原方法,前后记下时间,然后就可以获取方法的执行时间,这种做法有一个问题。如果项目中有很多控制器,在启动时就有大量的控制器需要交换方法,就会导致在早期的机型(5s)CPU 使用率过高,主线程卡顿的问题,而且多次启动后手机发热严重。我测了下方法的执行,发现瓶颈是在 method_exchangeImplementations(originalMethod, newMethod);这句又是系统的方法,想了一周,都没有想到好的办法。有没有别的办法的朋友?
    10 条回复    2017-03-16 14:10:24 +08:00
    chipmuck
        1
    chipmuck  
       2017-03-14 17:09:07 +08:00
    写个父类,所有 vc 都继承这个 vc 类,然后在父 vc 类中的 +load 里进行 hook ?
    loveuqian
        2
    loveuqian  
       2017-03-14 17:10:04 +08:00 via iPhone
    论基类的重要性
    changhogliang
        3
    changhogliang  
    OP
       2017-03-14 17:30:37 +08:00
    @chipmuck 我这是做 sdk 的,不能这样干。
    changhogliang
        4
    changhogliang  
    OP
       2017-03-14 17:32:59 +08:00
    现在想了一个办法,在启动时让进行 hook 的线程隔一段时间 sleep 一下,不知道这样干有没有什么潜在风险。
    chipmuck
        5
    chipmuck  
       2017-03-14 17:38:37 +08:00
    @changhogliang 在 sleep 的期间有个 vc 被创建了,但是还没有 hook 到,就无法监控了。
    changhogliang
        6
    changhogliang  
    OP
       2017-03-14 17:43:54 +08:00
    @chipmuck 存在这个问题,不过为了保证性能,实在是没有什么别的好办法。
    coa
        7
    coa  
       2017-03-15 00:37:04 +08:00
    不明白启动时为嘛一定要取得所有类,不应该直接针对 UIViewController 进行 hook 吗?还有其他类有 viewdidload 方法?这阶段对其他类的自省估计得浪费不少时间。。

    +load 不用起一个基类啊,正常姿势不是放在 category 么?+load 又不会被覆盖,也没啥侵入性, SDK 可以用吧。。

    sleep 一下估计不是好方法,莫名想起网络请求不用回调,估摸着 delay 个零点几秒再刷新 UI 这样的无语做法。。程序应该足够确定不应该依赖这一类“估摸”。。。

    不清楚 method_exchangeImplementations 为何会占用大量资源?这不是常用的 Method Swizzle 方式么。。实在是这个方法有问题,要不试试将 viewdidload 选择器 hook 到 objc_msgForward 的实现,强行进入消息转发,再 hook forwardInvocation ,再转 viewdidload 的实现?不过到 forwardInvocation 之前还有不少动作,感觉时间也不少。。还是觉得 method_exchangeImplementations 不该有问题。。。

    感觉朝 Method Swizzle 进行优化方向好像不大对,还是找找看有没有其他更直接的取得执行时间的方法靠谱些。。。
    changhogliang
        8
    changhogliang  
    OP
       2017-03-15 09:30:02 +08:00
    @coa1. 对 UIViewController 进行 hook 如何可以获取它子类的 viewdidload 的执行时间?放在分类里,应该对谁添加分类?我觉得必须对项目中创建的控制器进行 hook 才能正确获取方法执行时间,如果是 sdk ,你怎么获取项目中创建的控制器呢?
    2.其实我 hook 的不止这一个方法,控制器的生命周期方法都有 hook ,如果 hook 几个,几十个类没有问题,如果 hook 几百个的话,在 5s 上面就发热严重,我把 method_exchangeImplementations 注释掉,问题就不存在了。
    3.获取一个方法的执行时间,肯定是要在前面记个时间,方法执行后记个时间,这种除了 hook 应该没有别的办法了吧, hook 就绕不开 method_exchangeImplementations ,感觉这点消耗性能的操作必须要做。
    coa
        9
    coa  
       2017-03-15 23:21:08 +08:00
    @changhogliang 明白了,需要子类 viewdidload 后再执行,这种情况下 hook UIViewController 确实不管用。

    hook 除了 method_exchangeImplementations ,还有一个就是上边说的,将 originalMethod 的选择器指向 objc_msgForward 函数地址,在消息转发阶段进行有关操作。具体参考可翻下 Aspects 的源码。 Aspects 可以直接前后都 hook ,就是不知道控制器多的话会不会和 method_exchangeImplementations 一样出现发热问题。 SDK 允许引入第三方依赖的话可以先拖进去试一下,就千来行代码,体积应该可以接受,不允许再参考着自己写。如果同样发热的话估计得另寻他法了。。。
    changhogliang
        10
    changhogliang  
    OP
       2017-03-16 14:10:24 +08:00
    @coa 先谢谢了,这是一个思路,可以试试。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5406 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 02:48 PVG 10:48 LAX 18:48 JFK 21:48
    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