InjectionIII神器-让代码所见即所得
前言:iOS发开过程中,经常需要cmd+r进行编译、运行,然后跑到模拟器(手机)上。这在一个稍微大的项目上,是一个非常费时费力的操作。如果能够在项目编写完后,立刻看到目标效果,该是一件多么节约成本的事情。下面我将介绍InjectionIII,让iOS开发更简单~
在工程中使用InjectionIII
其实InjectionIII
安装非常简单,只需要在app store
中搜索InjectionIII
即可下载
有兴趣的可以到 github 查看更多文档。
在app工程中使用:
1.启动InjectionIII
,并选择要检测的项目
2.在AppDelegate
中的didFinishLaunchingWithOptions
方法中,添加如下代码:
#if DEBUG
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
#endif
项目运行后,在xcode中会看到如下文字打印即表示监听成功
console打印
3.在UIViewController
中,添加- injected
方法,可以看到,在使用cmd+s的时候,模拟器会根据- injected
中的修改,立刻更改界面。
技巧
可以创建一个InjectionIIIHelper
(.gitignore中可以添加该文件),用来专门做拦截操作 :
+ (void)load {
#if DEBUG
//注册项目启动监听
__block id observer =
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
//bundlePath
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}];
class_addMethod([NSObject class], NSSelectorFromString(@"injected"), (IMP)injected, "v@:");
#endif
}
可以看到,在文件被载入到内存(+load)的时候,就进行了上述步骤2的操作。并且,在每个类对象添加了无返回值、无参数的injected
方法(至于为什么是需要添加到类对象中,这个和OC运行时有关系,这里就不进行阐述了)。再进行如下代码拦截控制器和view,在cmd+s时响应loadView、viewDidLoad...等方法。
/**
InjectionIII 热部署会调用的一个方法,
runtime给VC绑定上之后,每次部署完就重新viewDidLoad
*/
void injected (id self, SEL _cmd) {
//vc 刷新
if ([self isKindOfClass:[UIViewController class]]) {
[self loadView];
[self viewDidLoad];
[self viewWillLayoutSubviews];
[self viewWillAppear:NO];
}
//view 刷新
else if ([self isKindOfClass:[UIView class]]){
UIViewController *vc = [InjectionIIIHelper viewControllerSupportView:self];
if (vc && [vc isKindOfClass:[UIViewController class]]) {
[vc loadView];
[vc viewDidLoad];
[vc viewWillLayoutSubviews];
[vc viewWillAppear:NO];
}
}
}
如果不使用远程、本地私有库的形式进行开发,上面的方法已经可以实现你的需求的。但是,如果使用到私有库开发环境,那么上面配置步骤还是需要进一步的修改。
在私有库中开发
通常,项目很大的时候,会通过远程、本地私有库的形式,进行项目分发。但是,如果通过私有库方式编程时,我们会发现,尽管已经按了cmd+s,项目依然没有进行刷新。这是因为,项目路径和和私有库路径并不在同一个位置。
我们需要做的就是将私有库内容和它的podspec
复制一份,放到项目路径中。并且修改项目的Podfile
指向改为_pod中的podspec
但是,如果在git同步开发的时候,如果将_pod中的内容提交到git,只会增加git中的代码量,并不会更改私有库路径下的代码。因此,我们需要将_pod目录添加到.gitignore,并且将_pod目录里的修改的内容,自动同步到私有库目录下。那,怎么将_pod目录下的内容,自动同步到私有库中呢?
这里介绍一个工具fswatch,可以监听文件的修改:
安装方法如下
创建一个脚本,监听修改、同步的内容:
watch_file=/Users/gtja/Documents/LocalLib/Example/_pod/LocalLib/
target_file=/Users/gtja/Documents/LocalLib/LocalLib/
# 将watch_file修改的内容,同步到target_file中
fswatch ${watch_file} | while read file;
do
rsync -trl --delete ${watch_file}/ ${target_file}/
echo "This file ${file} has changed."
done &
# 将从git拉取的内容同步到watch_file中
fswatch ${target_file} | while read file;
do
rsync -trl --delete ${target_file}/ ${watch_file}/
echo "This file ${file} has changed."
done &
在运行脚本后,可以看到,在私有库中开发的脚本,不仅可以运行到模拟器中,而且修改的代码,也自动添加到sourcetree(虽然修改的不是同一个文件)。
自动监听和同步最后,分享一下我的测试代码和脚本(sync.sh):测试代码和脚本