2013/12/16

iOSシミュレータの再起動なしでコード修正が即時反映できるようになるライブラリRestartLessOftenを使ってみる

UI周りのコードを微調整するためにコンパイルと実行を来り返すという状況は割とあることですが、毎回のアプリの起動は時間がかかるので、できる限り避けたいものです。

その回数を減らすことができるライブラリがRestartLessOftenです。

この記事ではRestartLessOftenの試しに使ってみたり、導入方法について紹介したりします。

使いかた

とりあえず体験するには、RestartLessOftenをGitHubより取ってきて、サンプルプロジェクトを起動させてください。

シミュレータを実行してから、コードを修正してコンパイルするだけで、内容が変化するのがわかります。

rlo_server.pyみたいなのもあって、実機上で利用するにはこれが必要みたいです。

なお、コードを反映はおおまかに言えば、次のようにして実現しているようです。

  1. xcodebuild-dry-runを実行して、修正されたファイルを検出。それをRLORebuildCode.mに書き出す
  2. そのソースをコンパイルしてバンドルにする
  3. バンドルをロードしてSwizzlingする

セットアップ

導入が非常にややこしいです。詳細はInstalling RLOを参照してください。

なお、自動更新対象となるターゲットをXcodeSampleとします。

  1. まずはリポジトリを取得しておきます。

    $ git clone https://github.com/mikr/RestartLessOften.git $ cd RestartLessOften

  2. メニュー → File → New → Target…で、iOS → Other → Cocoa Touch Unit Testing Bundleを選択します。[Product Name]はRLOUpdaterBundleXcodeSampleみたいにします。

  3. 今作成したターゲットのBuild Settingsを開きます。

  4. まず、Other linker flagsを削除します。

  5. こんなかんじです。

  6. 続いて、Generate Debug SymbolsをNoにしておきます。

  7. そのまま、隣りの[Build Phases]タブに移動します。

  8. メニュー → Editor → Add Build Phase → Add Run Script Build Phase。追加されたRun Scriptに次のコードを追加します。

    exec ${SRCROOT}/../../scripts/rlo_onbuildstart.sh RLOUpdaterBundle${TARGET_NAME}.xctest
    
  9. Run Scriptの名前をrlo_onbuildstartに変更します。

  10. 再度、メニュー → Editor → Add Build Phase → Add Run Script Build Phaseします。追加されたRun Scriptに次のコードを追加し、名前をrlo_onbuildendに変更します。

    exec ${SRCROOT}/../../scripts/rlo_onbuildend.sh

  11. rlo_onbuildstartをTarget Dependenciesに下に移動させます。

  12. 同様の手順でXcodeSampleにも、rlo_onbuildstartとrlo_onbuildendを作成します。

  13. Target Dependenciesに内容を削除し、XcodeSampleと同じにします。

  14. RLOUpdaterBundleXcodeSample.mを削除します。

  15. RLOUpdaterBundleXcodeSample-Prefix.pchに次のコードを追加します。

    #import "XcodeSample-Prefix.pch"
    
  16. RLORebuildCode.mが作成される場所であるRLORebuildCodeを作っておきます。

    $ cd ~/src/Sample/XcodeSample/              
    $ mkdir RLORebuildCode
    
  17. スクリプトをちゃんとした指定した場所に置いておきます

    cp ~/src/RestartLessOften/scripts/rlo_* ~/src/Sample/XcodeSample/../../scripts/
    
  18. RestartLessOftenからプロジェクトRLOClassesを追加します。

  19. XcodeSample-Prefix.pchの__OBJC__ブロックの中に次のコードを追加します。

    #if DEBUG
    #define RLO_ENABLED
    #import "RLODefinitions.h"
    #define RLO_CONFIG_PATH (RLO_BUNDLEUPDATE_SRCROOT "/rloconfig.py")
    #endif
    
  20. main.cの@autoreleasepoolブロックの中に次のコードを追加します。 #ifdef RLO_ENABLED RLO_WATCH_CODE_UPDATES; RLO_INIT_CONFIGURATION(RLO_CONFIG_PATH, RLO_SERVERURL); RLO_START_CONF_LOADER; #endif

以上です。

導入後に、各ViewControllerに次のコードを追加していきます。

  1. viewDidLoadに次のコードを追加

    RLOaddObserver(self, @selector(rloNotification:));
    
  2. deallocの末尾に次のコードを追加

    RLOremoveObserver(self);
    
  3. どこかに次のコードを追加

    #ifdef RLO_ENABLED
    - (void)rloNotification:(NSNotification *)aNotification
    {
        //[self configureView];
    }
    #endif
    

なお、手元の環境では、RLOUpdaterBundleXcodeSampleのCompile SourcesにRLOUpdaterBundleがないと更新されませんでした。

うまく動作しないときはサンプルプロジェクトの設定を参照してください。

おわりに

RestartLessOftenの使い方と導入方法について紹介しました。

  • 現状は導入に手間がかかる
  • 導入したら側使えるようになるわけではなく、ビューの更新をちゃんとさせるためのコードを入れる必要がある
  • Storyboardの修正は反映されなかった
  • CocoaPodを導入するとコンパイルに失敗する (が、更新されてたりする)

いろいろ問題はあるのですが、コンパイルしたらその修正が即座に反映されるのは非常に便利でした。

似たようなプロジェクトとして、 Injection for Xcodedyciがあるみたいなので、ここらもちょっと試してみるつもりです。

関連リンク

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。