我的女神——简洁实用的iOS代码调试框架
一、引言
这篇博客的起源是接手了公司的一个已经完成的项目,来做代码优化,项目工程很大,并且引入了很多公司内部的SDK,要搞清楚公司内部的这套框架,的确不是件容易的事,并且由于这个项目是多人开发的,在调试阶段会打印出巨量的调试信息,使得浏览有用信息变的十分困难,更加恐怖的是,很多信息是SDK中的调试打印,将这些都进行注销是非常费劲甚至不可能的事,于是便有了这样一些需求:首先,我需要清楚了解各个controller之间的跳转关系,需要快速的弄清每个stroyBoard中各个controller的来龙去脉,其次,我想在不改变其他人的调试代码的情况下,屏蔽冗余的log信息,让我的调试数据更加清晰明了。于是我想到了如下的解决方案,同样,如果你有更好的方案或者你知道的优秀的解决办法,请告知我,十分感谢。
二、追踪程序的跳转路径
这是一个很容易解决的问题,我们都知道,一个controller,如果要展现出来,一定会走生命周期中的viewWillAppear这个方法,我们只需要在这个方法中做些手脚就可以了,实现有两种思路,一种是采用工厂的设计模式,建立工厂类Controller,在其viewWillAppear中加入我们的调试代码,但这对于我的项目并不实用,首先我不确定所有controller都会继承于一个父类,其次,在我没有找到源头时,这些类已经在公司的framework中了,我根本没办法操作源码。而第二种方案就是runtime,对的,运行时的OC,没有不可能。关于runtime的详细说明,在http://my.oschina.net/u/2340880/blog/489072中有介绍。思路是我们可以写一个方法,替换掉系统的viewWillAppear,在其中加入我们的调试代码,这个方法就是Method Swizzing,代码设计如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
三、屏蔽冗余的log信息
1、系统的NSLog是个什么玩意
要战胜我们的敌人,首先应该了解我们的敌人,我们想要屏蔽NSLog的打印,先需要清楚NSLog到底是个什么玩意。
首先,NSLog的定义如下:
1 2 |
|
这里面有两个函数,一个是使用多参的格式化字符串进行NSLog的打印,一个是通过参数指针进行打印。从这里我们可以看出,系统的NSLog是一个C风格的函数,所以,我们有思路了,我们可以通过定义一个NSLog宏来替换掉项目中所有的NSLog,如下:
1 2 |
|
2、实现我们自己的NSLog
通过上面的方法,在没有动源码的情况下,我们已经可以替换掉程序中所有的打印,可能你会疑问,程序中怎么会允许我们有两个NSLog呢,其实这没什么神奇的,要知道宏是一种预编译的指令,所有这些操作是在代码编译之前完成的,实际上程序中已经将NSLog简单替换成了我们的函数调用,程序中只有一个NSLog,这就是宏的强大之处,狸猫换太子,不错吧。
下面我们来实现我们的这个函数,如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
这个函数中其实并没有做什么,加了一个锁的判断,仅此而已,核心的控制,就交给我们的锁吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
四、看看我们的杰作吧
做完上面的工作后,我们在appdelegate中如如下的简单配置:
1 2 3 4 5 6 7 8 |
|
我们做如下测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
我在viewController中的有用信息前后,打印了一些干扰信息,并且可以看到,这个NSLog的格式和系统的完全兼容,在打印有用信息前后解锁和加锁,结果如下:
可以看到,我们将没用的打印都屏蔽了,并且打印了程序的跳转流程。最重要的是,我们对源码一个字符都没有修改,同时不会影响与冲突其他人的开发。
这篇博客开头,我称之为我的女神,真心实感,这个方法帮了我很大的忙,在我了解项目的结构框架前,每次调试打印都在控制区滚出一片片的信息着实让我头晕脑胀,现在一清凉,精神也清爽不少,^_^。