アプリ開発録

iPhoneアプリやその他開発で得られた知見をメモ

『Interval Reminder』開発録 #3(finish)

インターバルリマインダーが配信開始しました。

Interval Reminder

Interval Reminder

  • Takumi Yoneta
  • 教育
  • ¥120

最終的に使用したライブラリ

検討していたライブラリはこうでした。

  • Realm
  • Chameleon
  • Permission Scope
  • Onboard
  • Appirater
  • fastlane

が、このうち、結局最終的に使用したのは以下のもののみとなりました。

  • Realm データベース
  • Chameleon UIのテーマカラー
  • Appirater 評価ページへの誘導
  • fastlane デプロイと申請の自動化、Git管理

fastlaneを使用しての申請

fastlaneを使用しての申請作業は初めてだったので、うまくできるか不安だったのですが、最終的にはちゃんとfastlaneのみで完遂できました。
スピード重視なので、かなりハマるようだったらいつも通り(と言っても2回目だが)の手作業でやろうとしたのでホッと安心。

参考にしたのは以下のページ。

qiita.com

qiita.com

qiita.com

また、Fastfileをどのようにすればいいのかは、以下のページを参考にした。

github.com

アップロードできなかった時に直した箇所

initした時に生成される初期設定のFastfileだと、アップロードに失敗した。

その原因はどうやらプロビジョニングプロファイルがなかったせいらしく、以下をつけたしたら自動的にダウンロードされうまくアップロードできるようになった。

sigh(
        app_identifier: "com.{yourname}.{appname}"
    )

この記述は、手作業で行うところの、

i-app-tec.com

このページで行っている部分に当たる。なのでこれは行わなくて済んだ。

最終的なFastfile

fastlane_version "2.45.0"

default_platform :ios

platform :ios do
  before_all do
    ENV["SLACK_URL"] = "{your slack hook URL}"
    cocoapods
    
  end

  desc "Runs all the tests"
  lane :test do
    scan
  end

  desc "Submit a new Beta Build to Apple TestFlight"
  desc "This will also make sure the profile is up to date"
  lane :beta do
    gym(scheme: "IntervalReminder")
    pilot
  end

  desc "Deploy a new version to the App Store"
  lane :release do
    sigh(
        app_identifier: "com.{yourname}.{appname}"
    )
    gym(
      workspace: "IntervalReminder.xcworkspace",
      scheme: "IntervalReminder",
      configuration: "Release"
    )
    deliver(
      force: true,
      skip_screenshots: true,  // ---[1]2回目以降で変更する必要のない時はtrue
      skip_metadata: true  // ---[1]同上。デフォルトはfalse
    )
    clean_build_artifacts  // ---[2]
  end


  after_all do |lane|
    slack(
      message: "Successfully deployed new App Update."
    )
  end

  error do |lane, exception|
    slack(
      message: exception.message,
      success: false
    )
  end
end

おそらく必要ない記述もあるだろうが、1回目でsighがなく失敗したのだが、原因がわからなかったので、サンプルを参考に色々足してみた結果がこうなった。
本当はsighの記述だけで行けると思う。

また、(2)のclean_build_artifactsは、ビルドしてアップロードした後にビルドで使用したファイル(プロビジョニングプロファイル)も含めてクリーンに削除してくれる。
プロビジョニングプロファイルはその都度ダウンロードでも問題なく何度もアップロードできた。

fastlaneで行うAppleの二段階認証

fastlaneで行う初回のアップロード時に、ターミナルに英語で2段階認証でどうたらこうたら出て、AppleIDのページにアクセスしてどうにかしろというメッセージが出た。

f:id:tak-dev:20170714103727p:plain ▲これかと思ったがこれではない。

  1. 普通にAppleIDのパスを入れるも通らない
  2. AppleIDのページでログインする時に出る、番号をそこに打つのかと初めは思ったので、それを打っても認証が通らない。

と両者試して通らなかったので、どうすればいいかわからず困惑。

調べたらAPP-SPECIFIC PASSWORDSなるものがAppleIDのSecurityの中に存在するらしく、ここで生成したパスワードを入力するらしかった。

f:id:tak-dev:20170714104147p:plain

GeneratedをクリックするとUse an app-specific password to sign in to an app or service not provided by Apple.と表示されるのでそこには、このパスワードを使う用途などをメモを記述しCreateを押す。

そうすると、自動的にランダムなパスワードが生成されるので、それをターミナルに打つことでfastlaneからItunes Connectへのアップロードができるようになった。

怪奇現象、バイナリのアップロードに成功してもItunes connectからバイナリがすぐ消える

バイナリのアップロードが完了しても、バイナリのページから該当のバイナリが消えてしまう現象が置きた。

なにかの見間違いかと思い、何度もアップロードするも再現率は100%。

しばらくどうしたらいいかわからなかったが、メールボックスを見るとAppleからのメールが届いていた。
気づかないので、ページのほうでなんらかのメッセージくらい出して欲しい。

具体的なメール内容はこれ。

Dear developer,

We have discovered one or more issues with your recent delivery for "Interval Reminder". To process your delivery, the following issues must be corrected:

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSContactsUsageDescription key with a string value explaining to the user how the app uses this data.

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data.

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSBluetoothPeripheralUsageDescription key with a string value explaining to the user how the app uses this data.

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSMicrophoneUsageDescription key with a string value explaining to the user how the app uses this data.

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSMotionUsageDescription key with a string value explaining to the user how the app uses this data.

Once these issues have been corrected, you can then redeliver the corrected binary.

Regards,

The App Store teamz

使用している機能のうち、プライバシーのためにInfo.plistへの記述が足りないという警告。

しかしメールで注意されている、NSContactsUsageDescriptionNSCalendarsUsageDescription等、どれひとつこのアプリでは使用していないし全く心当たりがなかったので当惑。

まさか、サードパーティライブラリのせいかと思いつき、使用していないPermission ScopeをCocoa Podsの記述から削除すると上記の警告がなくなった。

Permission Scopeの罠

Permission Scopeは結局使用しなかったのだが、次回以降のアップデートで使うつもりだったので、そのままビルドして申請したところ、上記のようなメールが届いた。

だがこれを消すとなくなったので、結局犯人はPermission Scopeだった。

ということで、自分のアプリで使用していなくてもライブラリの方で使っている場合もあるのだなと学習になった。

qiita.com

github.com

それでもまだ問題があった

Permission Scopeを削除してアップロードしても、まだ以下のようなメールが届いた。

Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.

Once these issues have been corrected, you can then redeliver the corrected binary.

今度はNSPhotoLibraryUsageDescriptionだ。だが当然ながらフォトライブラリーにアクセスするような機能は今回のアプリでは搭載していない。

またライブラリによる使用だが、使用しているライブラリを特定するのも面倒そうだし、そもそも特定したところで、使用しているから削れない。

ということで、審査に通るかわからないが以下のような記述で押し通せるか試してみた。

<key>NSPhotoLibraryUsageDescription</key>
<string>Do not use by this app. but third party Library includes that code.</string>

要約すると、「使っているライブラリが使っているだけで、このアプリでは使用していない」と書いた。

参考にしたページでは

とれる対応としては以下のいずれかでしょう。 - plistにまっとうな理由を書く - ライブラリを使うのをやめる

Appleからの公式見解も出ています。 https://forums.developer.apple.com/message/176579#176579

前者に対応する場合、ライブラリ提供元に問い合わせて、どのような用途で上記コードを使っているかを問い合わせる必要がありそうです(そのうちアナウンスがあるかもしれません)。

と、あったので、果たしてこんな記述で審査に通るか不安だったが、「ライブラリ提供元に問い合わせて、どのような用途で上記コードを使っているかを問い合わせる」はあまりにも時間がかかるので他に仕様がなかったので、これでダメ元で提出。

結果的には配信開始されたので、こういった記述でも問題なかったようだ。

Itunes connect「契約保留中」の罠

上記諸々で開発の罠はくぐり抜けたのだが、最後の最後で罠が待っていた。

アプリ申請後、2日くらいで順調に「レビュー待ち」→「レビュー中」と進んでいったのだが、「契約保留中」という前のアプリの時には見られなかったステータスに変更された。

何か問題があったのかとドキッとしたがメールも何も届いていない。

Googleで調べてみても、なんか勝手に進むみたいな記述があったのでそのまま数日放置。しかし一向に配信されない。

おかしいと思って再度調べてみると、どうやらこれは有料アプリにした時の、銀行の情報や、契約関係の同意が足りない時に出るステータスらしい。

処女作アプリでは無料だったので、このプロセスが必要なかったのだ。

ということで、以下のページを参考に契約情報を更新した。

iTunes connectで入金口座の登録をしよう | onTheHammock LLC

Swift:iTunes Connectの登録作業を実施 | raizan2ame

無事、配信開始

ということで、様々なハマりポイントや罠をくぐり抜け、なんとか初の有料アプリを配信することができました。

なにかの参考になれば幸いです。

ストアのサンプル画像をどうやって作ったか

f:id:tak-dev:20170715105538p:plain ▲これ

はじめは、こういった画像を簡単に作成できるサービスである「Useful Tools for Mobile App Creators | LaunchKit」を使おうと思っていたのだが、どうやらGoogleへ買収されてオープンソース化してしまい、サービスが稼働していない模様。

これを使うにはVagrantVirtualBox等を用いて自分で環境を構築する必要があるようだ。

なのでVirtualBoxを落としてVagrantも導入して行おうと思ったのだが、現状のLaunchKitは、最新のVirtualBoxに対応していないらしく、古いバージョンもDLできなくなっていたので断念。

同類のサービスである「DaVinci Apps – Create customized App Store screenshots for you iPhone and Android app」を使うことに。

しかしこちらは無料枠だと画像全面に透かしが入ってしまい使い物にならなかった。有料枠は年払いしかなく、そこまで高頻度に使用するわけでもないのでこちらも断念。

結局、DaVinci Appsで出力した透かしの画像をテンプレートに、無料素材等を用いて自分でPhotoshopで組み上げることにし完成。

追記:こんなサービス出たそうです

dimmy.club

今回使ったライブラリの感想

Realm 素晴らしい。UserObjectsは二度と使わないと思う。

Chameleon なくてもなんとかなるけどスピード重視して頭使いたくない場合は有効。

fastlane いいね

次回以降チャレンジしたいこと