iOSアプリの開発において、デバッガーをアタッチできないときのデバッグは骨が折れます。その最たる例がPush通知から起動するときだと個人的には思います。

アプリが起動していない状況から起動するときに挙動を検証する際には、そもそもアプリが起動しておらずプロセスが存在しないためデバッガーをアタッチすることもできません。

そこでせめてもの抵抗でprintデバッグをしようと組み込みのprint関数でログを出してみるのですが、実機ログをみると色々なログがごちゃまぜになっていて必要なログだけに絞り込むのがなかなか難しいです。

この際作っちゃろかと一瞬思ったんですが、ちょっと調べたらすぐに見つかったんでそれを使いました。

ログを記録するクライアントライブラリと、それを受け取るサーバーをセットで使います。

自分のローカル環境だけ、しかも一時的に使えれば良いという前提で今日の話をします。

ログを受け取って標準出力に出すサーバー

rubyで書かれた、rack-http-loggerなるものを使えます。後述するiOS側のクライアントアプリと同じ人が書いてて、すぐ使えます。

mattt/rack-http-logger
Log metrics from HTTP request parameters according to l2met conventions - mattt/rack-http-logger
% git clone https://github.com/mattt/rack-http-logger
% cd rack-http-logger/example
% bundle install
% thin start

これでlocalhost:3000にサーバーが立ち上がります。

ログを記録するためのクライアントライブラリ

Antennaというライブラリを使います。cocoapodsで導入可能。

mattt/Antenna
Extensible Remote Logging for iOS. Contribute to mattt/Antenna development by creating an account on GitHub.

すごく古いですがちゃんと使えます。

Podfileにpod "Antenna"と書いてpod installします。

で、AppDelegate.swiftに初期化処理を書いておきます。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // さきほどのサーバーを指定
  Antenna.sharedLogger()?.addChannel(with: URL(string: "http://localhost:3000")!, method: "LOG")

  // 略
}

初期化後は必要な箇所でメッセージを渡して呼び出せばOK。

Antenna.sharedLogger()?.log("記録したいメッセージ")

さっきthin startしたコンソールに次のようなログが出ているかと思います。

source=rack-http-logger locale=ja_US message=記録したいメッセージ uuid=xxxxxxxxxxx

実際こんな感じで流れてきます。

これらを使えばデバッガーをつなぐことができなくても、変数をある程度確認したり、想定通りのコードを通るかどうかを確認したりできるわけです。

だいぶ古いツール郡なので新しいのがありそうだと思うのと、これだけシンプルな使い方しかしないならもっと簡単に作れてもいいんじゃないかと思ったりしています。