我们在调试iOS原生代码时,每次修改都需要Command+R来重新编译运行。当项目代码量很大,编译时间就会很漫长。因此对于开发中来说,如果能加快编译速度,能大大提高生产效率。如果我们能像Swift Playground、小程序或网页那样修改代码后能实时在界面上反馈出来就好了。然鹅,还真的有这样的Xcode插件,让你可以修改代码后立即在模拟器或真机上看到改变,它便是Injection for Xcode,这是官方的演示效果:
安装
可以通过Alcatraz、或直接在github上clone下来,然后build InjectionPluginLite/InjectionPlugin.xcodeproj。最简单的就是到App Store下载安装即可。(注意安装时先退出Xcode,安装完成后再打开Xcode,以保证Xcode能顺利加载插件)
使用方法
- 运行Injection,然后确保勾选了File Watcher
2.如果用的是Xcode10.2及以上,直接打开项目AppDelegate.m 在didFinishLaunchingWithOptions:中添加代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
#if DEBUG
// for iOS
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection10.bundle"] load];
// for tvOS
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/tvOSInjection10.bundle"] load];
// for masOS
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/macOSInjection10.bundle"] load];
#endif
return YES;
}
如果是swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
#if DEBUG
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/iOSInjection10.bundle")?.load()
//for tvOS:
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/tvOSInjection10.bundle")?.load()
//Or for macOS:
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/macOSInjection10.bundle")?.load()
#endif
return true
}
- 最后在需要实时监听修改的地方重写injected方法,如在首页的ViewController.m中:
- (void)injected{
NSLog(@“I’ve been injected: %@”, self);
}
效果
现在运行项目,并调整UI相关的代码,模拟器或真机上面就会立即显示对应的效果。我最近在做一个iPad的项目,涉及UI调试的内容比较多,此时就能高效率地调试项目啦。
例如:原来的图片是yaun.png:
我在重写的injected方法中打了断点,然后把原来的yuan.png改成yi.png:
[yuan setImage:[UIImage imageFileName:@"main_section_button_yuan.png"] forState:0];
改为
[yuan setImage:[UIImage imageFileName:@"main_section_button_yi.png"] forState:0];
修改并Command+s保存后,此时会停到我们上面的断点处:
跳过断点,我们看到界面进行了更新:
原理
在Xcode端,Injection监听源代码的变化,如果有改动,Injection会将对应的类重新编译打包成动态库,也就是.dylib文件,然后通过Socket通知App。App收到消息后,加载动态库,此时会有被修改类的新、旧两个版本,然后利用runtime的方法动态替换,用新类替换旧类,从而达到不用重新编译运行而更新App。
参考
- injectionforxcode官方:https://github.com/johnno1962/injectionforxcode
- https://www.cnblogs.com/li-wei203/p/9851860.html
- 戴铭的iOS开发高手课《App 如何通过注入动态库的方式实现极速编译调
试?》