前言:iOS發(fā)開過程中,經(jīng)常需要cmd+r進(jìn)行編譯、運(yùn)行,然后跑到模擬器(手機(jī))上。這在一個稍微大的項目上,是一個非常費(fèi)時費(fèi)力的操作。如果能夠在項目編寫完后,立刻看到目標(biāo)效果,該是一件多么節(jié)約成本的事情。下面我將介紹InjectionIII,讓iOS開發(fā)更簡單~
在工程中使用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
項目運(yùn)行后,在xcode中會看到如下文字打印即表示監(jiān)聽成功

3.在UIViewController中,添加- injected方法,可以看到,在使用cmd+s的時候,模擬器會根據(jù)- injected中的修改,立刻更改界面。
技巧
可以創(chuàng)建一個InjectionIIIHelper(.gitignore中可以添加該文件),用來專門做攔截操作 :
+ (void)load {
#if DEBUG
//注冊項目啟動監(jiān)聽
__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
}
可以看到,在文件被載入到內(nèi)存(+load)的時候,就進(jìn)行了上述步驟2的操作。并且,在每個類對象添加了無返回值、無參數(shù)的injected方法(至于為什么是需要添加到類對象中,這個和OC運(yùn)行時有關(guān)系,這里就不進(jìn)行闡述了)。再進(jìn)行如下代碼攔截控制器和view,在cmd+s時響應(yīng)loadView、viewDidLoad...等方法。
/**
InjectionIII 熱部署會調(diào)用的一個方法,
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];
}
}
}
如果不使用遠(yuǎn)程、本地私有庫的形式進(jìn)行開發(fā),上面的方法已經(jīng)可以實現(xiàn)你的需求的。但是,如果使用到私有庫開發(fā)環(huán)境,那么上面配置步驟還是需要進(jìn)一步的修改。
在私有庫中開發(fā)
通常,項目很大的時候,會通過遠(yuǎn)程、本地私有庫的形式,進(jìn)行項目分發(fā)。但是,如果通過私有庫方式編程時,我們會發(fā)現(xiàn),盡管已經(jīng)按了cmd+s,項目依然沒有進(jìn)行刷新。這是因為,項目路徑和和私有庫路徑并不在同一個位置。

我們需要做的就是將私有庫內(nèi)容和它的podspec復(fù)制一份,放到項目路徑中。并且修改項目的Podfile指向改為_pod中的podspec


但是,如果在git同步開發(fā)的時候,如果將_pod中的內(nèi)容提交到git,只會增加git中的代碼量,并不會更改私有庫路徑下的代碼。因此,我們需要將_pod目錄添加到.gitignore,并且將_pod目錄里的修改的內(nèi)容,自動同步到私有庫目錄下。那,怎么將_pod目錄下的內(nèi)容,自動同步到私有庫中呢?
這里介紹一個工具fswatch,可以監(jiān)聽文件的修改:
安裝方法如下

創(chuàng)建一個腳本,監(jiān)聽修改、同步的內(nèi)容:
watch_file=/Users/gtja/Documents/LocalLib/Example/_pod/LocalLib/
target_file=/Users/gtja/Documents/LocalLib/LocalLib/
# 將watch_file修改的內(nèi)容,同步到target_file中
fswatch ${watch_file} | while read file;
do
rsync -trl --delete ${watch_file}/ ${target_file}/
echo "This file ${file} has changed."
done &
# 將從git拉取的內(nèi)容同步到watch_file中
fswatch ${target_file} | while read file;
do
rsync -trl --delete ${target_file}/ ${watch_file}/
echo "This file ${file} has changed."
done &
在運(yùn)行腳本后,可以看到,在私有庫中開發(fā)的腳本,不僅可以運(yùn)行到模擬器中,而且修改的代碼,也自動添加到sourcetree(雖然修改的不是同一個文件)。

最后,分享一下我的測試代碼和腳本(sync.sh):測試代碼和腳本