以前iPadだけでアプリを作るというエントリを書いていました。このエントリはその続編です。
以前のエントリでは、iPadだけで作ったアプリをストアに出すという目標は達成できていました。次はそれなりに実用的なアプリをiPadメインで作ってみたいなと思っていました。
ということで作ったのが、PhotoGuesserです!
apps.apple.comPhotoGuesserの紹介
アプリをインストールして使ってもらうのがわかりやすいと思います。GeoGuessrにインスパイアされて作ったもので、写真アルバムから写真がランダムで出てきます。写真を撮った位置を思い出して、地図上にピンを打つというゲームチックなアプリです。
自分の写真アルバムにある写真なので、全く身に覚えのない写真はないはず。アプリがランダムで出してくる写真から、当時のことを思い出したりすることができます。
ネイティブアプリは、OSとの連携が簡単にできるのが利点の一つです。ウェブにも様々なセンサー値を取得するAPIなどは追加されていますが、OSと統合した体験を作ることはやはりネイティブアプリに一日の長があります。写真アルバムへのアクセスはその最たる例ですし、歩数や睡眠などのヘルスケアの情報や、カレンダーやリマインダーとの連携も可能です。
とりあえず!僕がプレイしている動画を撮ったので見てみてください!
OSの機能、アプリ内課金、i18n
iPadでアプリを作るにあたって、入れたかったものが3つあります。それが、OSの機能、アプリ内課金、i18n。今回のPhotoGuesserでは、OSの機能は写真アルバムへのアクセスとして。アプリ内課金はサブスクリプションを、i18nは英語への翻訳をそれぞれ実装しています。
OSの機能 写真アルバムへのアクセス
ネイティブアプリを作る上での利点はOSとの統合です。なので、今回は写真アルバムへのアクセスをするアプリを作ってみました。
写真アルバムにはしばらくみていない写真が埋もれがちだと思います。つまり、宝の山です!今回は昔を思い出して懐かしむことを主眼に考えてみましたが、機械学習に通してみたり、Exifの情報を見てみたり、スクリーンショットを集めてみたり、色々考えられると思います!
iPadだけでアプリを作るために使っているSwift Playgroundsでは、写真アルバムへのアクセスは自然に追加できるので、特に難しいことをしなくても、ドキュメントを見て実装していくだけです!
アプリ内課金
作ったアプリは、有料で販売するか、無料で販売してアプリ内課金でマネタイズする、というのが良くあるパターンです。昨今はアプリ内課金があるアプリが多いですね。iPadだけで作ったアプリでもアプリ内課金は使えるのでしょうか?と思ったので、今回試してみました。
結論から言うと、StoreKitのライブラリが普通に使えます!なので、アプリ内課金を使うアプリは作れます!ただし、動作確認のためにTestFlightへのアップロードが必要です。
Swift Playgrounds上での実行では、StoreKitのAPIは正常に動作しませんでした。でも、勘で実装して、TestFlightにアップロードをしてみると、ちゃんとアプリ内課金が動作しました!その後審査に出して、ストアへの公開も試してみましたが、ストアでも正常に動くことが確認できています。
ただし、勘で実装するのは辛いですね。ストアのビューなどは、StoreKit 2でOSが提供してくれているビューが使えます。こういうものを有効活用していくと、とりあえずアプリ内課金ができるだけのアプリなら、かなり少ないコードで実装できます。
でも、やっぱりアプリ内課金みたいな重要な機能は作り込みたいですよね。作り込むためにはiPadだけ、つまりSwift Playgroundsでは厳しいと判断し、Xcodeと連携する方法を模索していました。
Swift PlaygroundsとXcodeの連携
色々考えて、ピタッとハマる解決策がないなぁと思っていたのですが、Xcode 16で全てが解決できました。リポジトリはこちらです。
XcodeAndPlaygrounds.swiftpm を開くとiPadで開発ができて、xcode-and-playgrounds.xcodeprojを開くとXcodeで開発ができます。swiftpmはgitのsubmoduleで連携しても良いですね。PhotoGuesserではsubmoduleのパターンで実装をしています。
これの肝は、Playgrounds側のソースコードはディレクトリに入れることと、そのディレクトリをXcode 16のフォルダーリファレンスでXcodeのプロジェクトにリンクすることです。こうすることで、Swift PlaygroundsとXcodeで同じファイルを参照でき、普段の開発はiPadでSwift Playgroundsを使って。アプリ内課金のようなPlaygroundsでは開発しにくい機能に関しては、Xcodeのプロジェクトを開き、StoreKit Configurationを読み込ませることができ、シミュレータを起動して、快適に開発が行えます。
気をつけなければいけないのは、Tintやプライバシーの設定などを二重に書く必要があること。Playgrounds側のPackage.swiftに書いてある設定は、Xcodeのプロジェクトでは読み込んでくれないので、今は手動でどっちにも書いています。今の僕はXcode側では手元ビルドだけで、アップロードなどはiPad上からやっているので、動けばいいやの精神で適当にそれっぽく合わせています。
iPadだけで完結しないのはズルい気もしますが、アプリ内課金を除いた普段の開発はiPadで完結できるので、僕は結構満足して使っています。普段からパソコンを持ち歩いている人は、そろそろ普通のXcodeのプロジェクトで開発するのを考えるべき頃合いかもしれないですね・・・!
i18n ローカライズ
もう一つ挑戦したいものとしては、ローカライズでした。Swift Playgroundsでのローカライズは、Package.swiftにdefaultLocalizationを指定した後に、Xcodeに昔からあるローカライズの手段である、Localizableの形式でファイルをプロジェクトルートに置くと、行えるようでした。
ただ、これはiPadでやるのはつらい。これを地道にやってもいいのですが、Xcodeとの連携をやっていたので、もっと楽できないかを考えてみました。現代において、ローカライズはString Catalogsが一般的です。なので、Xcodeと組み合わせてString Catalogsを使えるようにしていきましょう。
XcodeのプロジェクトにString Catalogsを追加した後、ビルドすると通常通りビルド時のリソースを参照して、テーブルが作成されます。ここにどんどん翻訳していく形になります。
あとはこれを、Playgrounds側の方に持っていくだけ・・・だと動かなかったので、String Catalogsの形式をLocalizableに変換できるツールがXcodeに用意されていたので、これを使います。
$(xcode-select -p)/usr/bin/xcstringstool compile xcode-and-playgrounds/Localizable.xcstrings --output-directory ./XcodeAndPlaygrounds.swiftpm/Localizable
つまり、以下のようなフローを辿ってローカライズを実現しています。
- iPadで開発する
- 一瞬Xcodeに戻ってきてビルドする
- Xcodeで翻訳する String Catalogsが使える
- コマンドを叩いてPlaygrounds側に反映する
- iPadでローカライズが反映される
ちょっと大変ですが、Localizableを手作業で頑張るよりはマシかな、と思いこの方法をとっています。やっていることの全体は、このコミットがわかりやすいと思います。 https://github.com/kouki-dan/xcode-and-playgrounds/commit/a124fa688e27d5dce8f70d6dc5241fea9730564e
まとめ
ということで、iPadだけでアプリを作ろうと頑張っていたけど、ちょっと頑張ろうと思うと結局MacとXcodeが欲しくなるね!という話題でした。iPadでのアプリ開発は多分4段階くらいあると思っていて
1段階目: iPadのPlaygroundsで完結させる 前に書いた記事の状態
2段階目: 開発やビルド、アップロードなどはiPadのPlaygroundsで完結させる、補助的にXcodeを使う この記事の状態
3段階目: 日常的な開発ではiPadを使う、iPadでできないライブラリや機能の使用のためにXcodeを使う。アップロードもXcodeで行う。 僕もまだ試していないもの
4段階目: iPadで開発するのは諦めて普通にXcodeを使う
という感じになると思っています。どこまでiPadでやりたいかは人によりますね。僕は普段iPadだけを持って温泉に行ったりするので、そういう時にふとプログラミングをしたくなった時の手段として、iPadで開発できるアプリを持っておきたい、という目的でやっていますが、同じ人は少なさそうです。そういう事情がない人は素直にXcodeを使いましょう!
Swift Playgroundsはなんでもできるわけではなくて、動かないライブラリが結構あります。例えば広告やFirebaseのライブラリを入れようとすると、2段階目ではどうしようもありません。その壁を越えたくなった時に3段階目でライブラリのインテグレーションだけをXcodeで行う、という段階が存在するのではないかな、と思っています。僕が直近で必要になっていないので試していないですが、今回の記事でやった2段階目をうまく発展させると動くでしょう、と思っています。
あとは、iPadメインで開発しているPhotoGuesser、結構面白いと思うので試してみてください!
apps.apple.comそういえばPhotoGuesserは、iOSDC 2024のアンカンファレンスでの題材に使っていたアプリで、細々とブラッシュアップを続けて先週公開したものです。iOSDC 2024のアンカンファレンスの話はiOSDC Japan 2024参加録にも少し詳しく書きました。この時に作った機能もちゃんとした形でアプリに実装しています。当日参加してくれた方々ありがとうございました!
アンカンファレンスでは、制限時間とヒント機能の実装をして、顧客からの無茶振り、プロジェクト管理の複雑さ、スタートアップの起こりなどを学びました!#iosdc https://t.co/Me7eYPx94E
— こーき@だん (@kouki_dan) 2024年8月23日