iOSアプリの不具合を申請なしで修正しよう

  • このエントリーをはてなブックマークに追加

Yahoo! JAPAN Tech Advent Calendar 2016の2日目の記事です。一覧はこちら

2017年3月8日現在、Rollout SDKを利用したアプリが、Apple社へのリリース申請時にリジェクトされる事象がApple Developer Forums上で報告されています。 こちらの記事で紹介しているRollout.ioの利用については自己の判断の下お願い致します。

[Apple Developer Forums] https://forums.developer.apple.com/thread/73640

こんにちは。
ヤフー株式会社ヤフオク!カンパニー ヤフオク!開発本部アプリ開発部の田中です。

皆さんはiOSアプリの開発をしていて、不具合などが見つかった際に
アプリを素早く修正できたとしてもAppleの申請、審査に時間がかかってしまい
修正が反映されるまでに苦労をしたことはありますでしょうか?

今回はそんな苦労から解放されるサービスを紹介させていただきます。

Rollout.ioの紹介

Rollout.io icon Rollout.io

Rollout.ioはユーザーの手元へすでに配布されたアプリに対して、 修正を行い反映できるツールです。

Rollout.ioの仕組みについて

Rollout.ioはアプリに対してJavaScriptベースでリアルタイムコードパッチを当てるツールです。 dSYMファイルをRollout側に共有し、どのメソッドに対してどのようなパッチを当てるかを クライアント側にJSONで提供し、Rolloutライブラリが受け取ったJSONを解釈し、パッチを適用します。

セキュリティーリスクはないのか

アプリ側はdSymファイル(デバックシンボル群)を送信しているのみとのことで、 dSymファイルはクラッシュ解析などでも利用されるファイルであるため、リスクは低い。と言われています。 Rollout.ioからクライアントに渡されるパッチについてはRSAで暗号化されており、 クライアント側は署名確認をちゃんと行った上でパッチの適用をするため、 外部のパッチが適用されて実行される。ということも起きないということも彼らは言っています。 詳細についてはRollout.io公式のドキュメントをご覧ください https://rollout.io/security/

Appleのガイドラインに反さないのか

Rollout.ioはネイティブコードを変更することはなく、 JavaScriptを使用してパッチにロジックを追加するのみ。と説明されています。 この点はRolloutはAppleのガイドラインに準拠している。とのことです。

もちろん、使い方次第ではさまざまなことが可能であるため、 使う側がきちんとガイドラインを理解し、Rollout利用の運用を行うことが前提になるかと思います。

2017年3月8日現在、Rollout SDKを利用したアプリが、Apple社へのリリース申請時にリジェクトされる事象がApple Developer Forums上で報告されています。 こちらの記事で紹介しているRollout.ioの利用については自己の判断の下お願い致します。

[Apple Developer Forums] https://forums.developer.apple.com/thread/73640

Rollout.ioはネイティブコードを変更することはなく、 JavaScriptを使用してパッチにロジックを追加するのみ。と説明されています。 この点はRolloutはAppleのガイドラインに準拠している。とのことです。

もちろん、使い方次第ではさまざまなことが可能であるため、 使う側がきちんとガイドラインを理解し、Rollout利用の運用を行うことが前提になるかと思います。

導入方法

Rollout.io 上記の画面からまずアカウント登録を行います。LITEユーザーであれば無料で利用可能です。 アカウント登録し、ログインを行うとアプリ登録の画面に遷移します。 「add app」を押すと以下のような画面に遷移します。 rollout start 「Instal via Cocoapods」を押すと以下のような手順書が表示されます。 rollout start2

あとは対象アプリに対して手順通りに一つずつ実施するだけでRolloutの利用が可能になります。

実際に使ってみました

sample1 リンクが作動しない不具合への対処

  • 仕様
    • タップしたらアプリ内webviewでヤフオク!のウェブ版に遷移する
  • 起きている不具合
    • ボタンをタップしても反応しない
  • 回避策
    • タップされたらダイアログを表示しSafariで開くようにする
demo1app

iOSアプリの実装

@IBAction func linkButton(_ sender: UIButton) {
  // 中身が空なので当然何も起きない
}

Rollout上の修正

  • 画面中央あたりにあるセレクトボックスから「Show Alert」を選択する
    demo1
  • ダイアログに表示する内容を設定する
  • JavaScriptのコードが以下のように生成されるのでそのまま適用する
    // Get started with javascript docs:
    // http://support.rollout.io/v3.1.0/docs/getting-started-with-javascript
    
    ViewController.linkButton = function (
      sender // SwiftBox<UIButton>
      // self - SwiftBox<ViewController *>
      // R    - Rollout javascript namespace
    ) {
    
    self.originalImplementation(sender);
    R.showAlertView(
      'Safariを開きます',
      'ヤフオク!をSafariで開こうとしています',
      'Ok',
      function() {
    R.NSClassFromString('UIApplication').call('sharedApplication').call('openURL:', R.NSClassFromString('NSURL').call('URLWithString:', 'https://auctions.yahoo.co.jp/'));
      },
      'Cancel',
      function () {}
    );
    
    // End of editable area
    };
  • Rollout反映後にアプリ上の「ヤフオク!」をタップした結果

sample2 判定処理の誤りによる誤動作への対処

  • 仕様
    • 10までカウントしたら1に戻る
  • 起きている不具合
    • 仕様を誤解し、
20までカウントしたら1に戻る
  • 回避策
    • 10までカウントしたら1に戻す

demo2app

iOSアプリの実装

func countRestart(count : Int) -> Bool {
    // countが20未満ならfalse
    if (count < 20) { // 正しくは if (count < 10) {
        return false
    }
    // countが20を超えたらtrue
    return true
}

@IBAction func countButton(_ sender: UIButton) {
    var count : Int = Int(self.countLabel.text!)!

    // countが20を超えたら1に戻す
    if (countRestart(count: count)) {
        count = 1
    // countが20未満ならcountを1増やす
    } else {
        count = count+1
    }
    self.countLabel.text=String(count)
}

if文の判定が20未満となってるので当然、20までカウントされてしまう。
countRestartを修正し、10までカウントされたらtrueを返すようにしたい。

Rollout上のJavaScriptコード

// Get started with javascript docs:
// http://support.rollout.io/v3.1.0/docs/getting-started-with-javascript
ViewController.countRestart = function (
  count // SwiftBox<Int>
  // self - SwiftBox<ViewController *>
  // R    - Rollout javascript namespace
) {

returnValue = self.originalImplementation(count);

  if (count < 10) {
      returnValue = false;
  } else {
      returnValue = true;
  }

// End of editable area
  return returnValue;
};

上記のようにアプリ内のメソッドを指定し、引数を参照することも可能。
var returnValueにメソッドの返り値が格納されるため、
JavaScriptで改めて正しいif文を定義し、返り値を変更してあげることで修正完了。

その他の機能

  • エミュレーター上のテストはもちろん、テストする端末を登録し実機でも検証することが可能
  • テスト反映機能で自由にエミュレーター、実機でテストが可能
  • objective-c,swiftどちらにも対応
  • JavaScriptを書かずとも返り値だけを変更したい。などの修正をすること可能
  • 反映する対象はアプリのバージョンごとに指定することができる。古いバージョンに対してのみ反映することが可能。
  • 反映するパーセンテージの指定が可能。5%のユーザーにのみ反映することで様子をみたりすることが可能
  • チャット機能によってRollout側と随時相談が可能
  • Androidにも今後、対応予定。

追記

2017年3月8日、利用に関する注意を追記しました。

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加