Injection Plugin For Xcode github上的开源项目,Xcode插件。
对于iOS开发者来说,XCode有个另人十分难耐的特性——编译时长的问题。也许工作的时候你能够为自己找到一个闲下来喝杯咖啡的正当的借口,然而,多次的调试编译过程足以让你喝上好多杯咖啡了。应该说,Injection是iOS开发者的福音,它在很大程度上优化了XCode的性能,提升了开发者的工作效率。
Injection能够在app运行时动态地向Swift或者OC文件注入新代码并且即时地呈现在运行中的模拟器的app上,从而达到提高程序编译速度,提高开发效率的目的。开发者不需要重新编译重新运行整个项目,这样的优化使得编译周期从7秒缩短至1秒。从XCode的输出台来看,每次在进行代码注入之后都只会编译被注入了代码的文件。这么一听有点类似于增量编译。
设想这样一个场景,对于一个编译启动需要10分钟的项目,如果你想对某个功能的动画效果进行微调,是否意味着你需要以至少10分钟为一个调试周期去对你的改动进行测试,而injection则能够在程序运行时动态的改动方法实现,并呈现在模拟器上。
如果你会科学上网,可以到这里去看看injection 的 https://github.com/johnno1962/injectionforxcode ;
或者到这里去看看他的演示:https://www.youtube.com/watch?v=uftvtmyZ8TM;
对于Injection的安装使用,可以到第一个链接里下载package。Injection团队为开发者准备了一套傻瓜式的配置流程,基本上都是单击continue就行了,然后重启你的Xcode。装成功后你会看到product > injection plugin。此时你应该已经装成功了。点击 Product >Injection Plugin > Patch Project for Injection 选项, 之后插件会在main.m 中插入两段代码。
#ifdef DEBUG static char _inMainFilePath[] = __FILE__; static const char *_inIPAddresses[] = {"10.12.1.67", "127.0.0.1", 0}; #define INJECTION_ENABLED #import "/tmp/injectionforxcode/BundleInjection.h" #endif
这不会影响程序原有代码,如果要还原,随时可以通过点击 Revert Injection’s Changes 选项来还原。你可以开搞了。
用一个demo做实验,将project运行起来,在运行时对你的代码进行改动,可以使用快捷键Ctrl + =快速运行。也可以在 product > injection plugin > inject and reset app。 你会发现你改动的代码所在类的左上角有一个蓝色的进度条,一秒不到的时间就能够完成注入并运行在你的app上。当然,你也能够在你改动的代码的方法里边加上一个断点,快捷键Ctrl + = ,你会发现运行时会停在你设定的breakpoint上。
对于Swift文件injection好像还不能做到完美支持,github上有相关的解释,我还没有深入的尝试,有兴趣的童鞋可以去看看,顺便交流交流。
injection是Xcode IDE的一个扩展,允许你去对类的一个方法实现打补丁而不需要重启app。官方的原理如下:
It performs this by parsing the build logs of the application to determine how a source file was last compiled. With this it wraps the result of re-compiling into a bundle which is injected into the application using the dynamic loader. At this point there are two versions of a class in the app, the original and a new modified version from the bundle. The modified version is then "swizzled" onto the original class so changes take effect.
(个人翻译)它通过解析程序的编译日志来确定最后一次编译的源文件。通过动态加载程序把重新编译的结果打包到被注入代码的app中。此时有两个版本的类应用,最初的和一个新的修改版本的包。这个修改后的版本,被“swizzled到”原始类中而生效。
除此之外,injection插件还有一个参数调节器Tunable Parameters,对于UI开发来说是个利器。比如对颜色的确定,对字体大小的界定等等。运行app,然后对参数进行修改就能够动态的进行调试了。直观而且方便。
对于 Tunable Parameters的使用我还没有涉足,它的使用目前仅限于Swift项目,还需要在项目中进行一些诸如添加头部代码的配置,有兴趣的童鞋可以到这里了解:https://github.com/johnno1962/injectionforxcode/blob/master/documentation/tunable_parameters.md 其实也不复杂,就是在新建一个main.m文件之后加上几行代码。
在使用injection时,一个新的Xcode项目文件将会在原本项目的文件里生成(iOSInjectionProject或OSXInjectionProject)。这个文件是用于存放那些被injecte的项目文件的,建议将其加入到.gitignore 中,直接忽略。
每一次的项目文件被injected,在injection项目目录里的injectionCount.txt中的数字就会增加。它可以很直观的告诉你节省了多少时间。
如果你想在真机或Appcode上进行测试:
你需要做一些轻量级的配置:在你的main.m文件加上如下几行代码:
#ifdef DEBUG
static char _inMainFilePath[] = __FILE__;
static const char *_inIPAddresses[] = {"10.12.1.67", "127.0.0.1", 0};
#define INJECTION_ENABLED
#import "/tmp/injectionforxcode/BundleInjection.h"
#endif
这个配置也可以通过Product > Injection Plugin > Patch Project For Injection 来进行自动配置。对于Swift文件,你需要添加一个空的main.m文件来完成配置。
至于使用Appcode的盆友,可以上github上看看教程:https://github.com/johnno1962/injectionforxcode
当然,injection并不是万能的,在某些情景下是不能起作用的。如下:
关于injection的局限性,在进行研究分析后我将会另开一篇进行论述。
对于某些童鞋的疑问:injection的编译效率与XCode自身的增量编译有什么优势?我已经在github上Issue了作者并得到了如下回复: