僅需七步, 讓你的iOS原生項目擁有Flutter熱重載極速調試
1. Mac的App Store上下載安裝InjectionIII.
image.png
2. 打開InjectionIII, Open Project, 選擇你的項目目錄.
image.png
3. 選擇的項目會在Open Recent中出現, 保持File Watcher的選項勾選.
4. 在AppDelegate的DidFinishLaunchingWithOptions配置InjectionIII的路徑
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
#ifdef DEBUG
//InjectionIII 注入
[[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
#else
#endif
return YES;
}
5. 在需要動態(tài)調試的頁面控制器中寫上injected
方法, 把需要操作的UI方法添加到injected
中執(zhí)行, 如果想讓全部的控制器都能使用, 直接添加到BaseViewController.
- (void)injected {
#ifdef DEBUG
NSLog(@"I've been injected: %@", self);
[self viewDidLoad];
#endif
}
6. 重新編譯項目, 控制臺可以看到
**?? InjectionIII connected /Users/***/Desktop/***/**/***.xcworkspace**
**?? Watching files under /Users/***/Desktop/****
// 下面的只是警告, 作者在Issue中已經解釋, 不耽誤正常使用.
**?? ?? ?? Your project file seems to be in the Desktop or Documents folder and may prevent InjectionIII working as it has special permissions.**
image.png
7. 修改完UI, 直接cmd + S
就能看到效果, 部分頁面可能耗時比較久或無法使用, 正常頁面均能使用.
enjoy :)
Flutter Hot Reload介紹
- Flutter是Google開發(fā)的一個跨平臺開發(fā)框架, 調試也是快速實時的.
- 在Flutter編輯器中修改文字代碼后, 點擊reload, App不用重啟, 模擬器的內容就會立刻改變.
- Flutter實現實時編譯的原理
- Flutter會在點擊reload時取查看上次編譯以后改動過的代碼, 重新編譯涉及到的代碼庫.
- 重新編譯過的庫會轉換成內核文件發(fā)到Dart VM里, DartVM會重新加載新的內核文件,
- 加載后會讓Flutter framework觸發(fā)所有的Widgets和Render Objects進行重建锄列、重布局图云、重繪.
- Flutter為了能夠支持跨平臺開發(fā), 使用了自研的Dart語言配合在App內集成Dart VM的方式運行Flutter程序.
iOS原生項目擁有Flutter熱重載的原理
- Injection for XCodeGitHub地址
- Injection工具可以動態(tài)地將iOS代碼在已運行的程序中執(zhí)行, 不用重啟.
- Injection會監(jiān)聽源代碼文件的變化, 如果文件被改動了,
- Injection Server就會執(zhí)行rebuildClass重新進行編譯右蕊、打包成動態(tài)庫.dylib文件,
- 編譯吮螺、打包成動態(tài)庫后, 使用writeString方法通過Socket通知運行的App.
- (BOOL)writeString:(NSString *)string {
const char *utf8 = string.UTF8String;
uint32_t length = (uint32_t)strlen(utf8);
if (write(clientSocket, &length, sizeof length) != sizeof length ||
write(clientSocket, utf8, length) != length)
return FALSE;
return TRUE;
}
- Server會在后臺發(fā)送和監(jiān)聽Socket消息, Client也會開啟一個后臺去發(fā)送和監(jiān)聽Socket消息.
- Client接收到消息后會調用
inject(tmpfile: String)
方法, 運行時進行類的動態(tài)替換(新類動態(tài)替換舊類).
- Client接收到消息后會調用
-
dlopen
會把tmpfile動態(tài)庫文件載入運行的App里, 返回指針dl.
-
- 接下來, dlsym會得到tmpfile動態(tài)庫的符號地址, 然后就可以處理類的替換工作了.
- 當類的方法都被替換后, 我們就可以開始重新繪制界面了.
- 使用動態(tài)庫方式極速調試, 整個過程無需重新編譯和重啟App.
image.png