使Xcode可以进行运行时调试功能的工具,可以理解为把项目变成了Playground。
本文主要针对戴铭专栏中“App 如何通过注入动态库的方式实现极速编译调试?”进行的总结。
注意
:需要注意第4节中提到的问题,修改过多地方的话,尽量还是重启App来调试。
1 安装和使用
1-1 安装
最简单的方法是从App Store下载安装InjectionIII,想体验最新feature的也可以从github上下载源码injectionforxcode
1-2 配置
//appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//...
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
return YES;
}
启动App后,会让我们选择项目路径,选择后就可以使用了。
修改后不会立刻生效,保存才能生效。
每次保存后,会自动调用当前controller的- (void)injected方法(如果重写了的话)。
1-3 查看修改
- 手动触发
如点击效果:点一下。
如布局变化,或网络请求:退出当前controller,再重新进入。 - 代码触发,在- (void)injected中手动调用
如布局变了,或网络请求:- (void)injected中调用viewWillLayoutSubviews、发送网络请求。
2 原理
- 启动了一个Mac App监听项目目录下的文件变化,并与模拟器建立通信
- 项目目录下的文件发生变化后,就重新打包动态链接库(多个单文件对应多个dylib动态库)
- 项目中InjectionIII Client端,收到Server端(Mac App)打包完成的socket消息,加载dylib,并执行Xcode焦点所在.m文件的inject方法。
对于项目来说,只记录了动态链接库的名字和路径,而不需要重新编译和链接。
链接器都做了什么
3 注意事项
- 只对模拟器有效。
- 支持OC和Swift。
- 使用了cocoapods的项目,如果希望监听pod中源码的修改,需要设置Legacy Build System。
默认的New Build System(Default)模式,不编译pod 里面的改动
设置方法:File -> Workspace Setting -> Build System, 改为Legacy Build System模式。
- 监听另一个项目时,通过InjectionIII重新选择监听目录。
- 不要修改进行了swizzling的类,否则二次交换,会造成死循环。
4 值得注意的问题
- 不支持方法的删除:删除后,方法调用仍然有效,不抛异常。
- 不支持新增类:新增类引入后使用无效。但类的重命名是有效的。
- 属性新增、删除、修改:反射上体现不出来。
在我看来,
问题原因,可能与苹果动态库调用的实现有关,不是InjectionIII工具的问题。
因为这些问题在动态库打包时也会出现:修改动态库源码,不修改版本号,重新打包(清过缓存也一样)。
另外,问题原因应该与加载时机无关,虽然动态库的路径绑定是在main之前进行的,而Injection是在didLaunch中才加载的。但是重命名类有效,说明这个路径绑定是有效的。