前言: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中會看到如下文字打印即表示監聽成功
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):測試代碼和腳本