僅需七步, 讓你的iOS原生項(xiàng)目擁有Flutter熱重載極速調(diào)試

僅需七步, 讓你的iOS原生項(xiàng)目擁有Flutter熱重載極速調(diào)試

1. Mac的App Store上下載安裝InjectionIII.

image.png

2. 打開(kāi)InjectionIII, Open Project, 選擇你的項(xiàng)目目錄.

image.png

3. 選擇的項(xiàng)目會(huì)在Open Recent中出現(xiàn), 保持File Watcher的選項(xiàng)勾選.

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. 在需要?jiǎng)討B(tài)調(diào)試的頁(yè)面控制器中寫(xiě)上injected方法, 把需要操作的UI方法添加到injected中執(zhí)行, 如果想讓全部的控制器都能使用, 直接添加到BaseViewController.

- (void)injected {
    #ifdef DEBUG
        NSLog(@"I've been injected: %@", self);
        [self viewDidLoad];
    #endif    
}

6. 重新編譯項(xiàng)目, 控制臺(tái)可以看到

**?? InjectionIII connected /Users/***/Desktop/***/**/***.xcworkspace**
**?? Watching files under /Users/***/Desktop/****
// 下面的只是警告, 作者在Issue中已經(jīng)解釋, 不耽誤正常使用.
**?? ?? ?? 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就能看到效果, 部分頁(yè)面可能耗時(shí)比較久或無(wú)法使用, 正常頁(yè)面均能使用.

enjoy :)

Flutter Hot Reload介紹

  • Flutter是Google開(kāi)發(fā)的一個(gè)跨平臺(tái)開(kāi)發(fā)框架, 調(diào)試也是快速實(shí)時(shí)的.
  • 在Flutter編輯器中修改文字代碼后, 點(diǎn)擊reload, App不用重啟, 模擬器的內(nèi)容就會(huì)立刻改變.
  • Flutter實(shí)現(xiàn)實(shí)時(shí)編譯的原理
    • Flutter會(huì)在點(diǎn)擊reload時(shí)取查看上次編譯以后改動(dòng)過(guò)的代碼, 重新編譯涉及到的代碼庫(kù).
    • 重新編譯過(guò)的庫(kù)會(huì)轉(zhuǎn)換成內(nèi)核文件發(fā)到Dart VM里, DartVM會(huì)重新加載新的內(nèi)核文件,
    • 加載后會(huì)讓Flutter framework觸發(fā)所有的Widgets和Render Objects進(jìn)行重建、重布局、重繪.
  • Flutter為了能夠支持跨平臺(tái)開(kāi)發(fā), 使用了自研的Dart語(yǔ)言配合在App內(nèi)集成Dart VM的方式運(yùn)行Flutter程序.

iOS原生項(xiàng)目擁有Flutter熱重載的原理

  • Injection for XCodeGitHub地址
  • Injection工具可以動(dòng)態(tài)地將iOS代碼在已運(yùn)行的程序中執(zhí)行, 不用重啟.
    • Injection會(huì)監(jiān)聽(tīng)源代碼文件的變化, 如果文件被改動(dòng)了,
    • Injection Server就會(huì)執(zhí)行rebuildClass重新進(jìn)行編譯、打包成動(dòng)態(tài)庫(kù).dylib文件,
    • 編譯、打包成動(dòng)態(tài)庫(kù)后, 使用writeString方法通過(guò)Socket通知運(yùn)行的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會(huì)在后臺(tái)發(fā)送和監(jiān)聽(tīng)Socket消息, Client也會(huì)開(kāi)啟一個(gè)后臺(tái)去發(fā)送和監(jiān)聽(tīng)Socket消息.
    • Client接收到消息后會(huì)調(diào)用inject(tmpfile: String)方法, 運(yùn)行時(shí)進(jìn)行類(lèi)的動(dòng)態(tài)替換(新類(lèi)動(dòng)態(tài)替換舊類(lèi)).
    • dlopen會(huì)把tmpfile動(dòng)態(tài)庫(kù)文件載入運(yùn)行的App里, 返回指針dl.
    • 接下來(lái), dlsym會(huì)得到tmpfile動(dòng)態(tài)庫(kù)的符號(hào)地址, 然后就可以處理類(lèi)的替換工作了.
    • 當(dāng)類(lèi)的方法都被替換后, 我們就可以開(kāi)始重新繪制界面了.
    • 使用動(dòng)態(tài)庫(kù)方式極速調(diào)試, 整個(gè)過(guò)程無(wú)需重新編譯和重啟App.
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容