Show original
Try the app

TuneDice
Enjoyed this article?
Use "Request tipping" to ask the author to set up tip receiving.

AI translation
Development Record of a Random Selection App for Karaoke Made with Swift + MusicKit for Swift
Try the app

TuneDice
Enjoyed this article?
Use "Request tipping" to ask the author to set up tip receiving.
I often felt subtle stress from the fact that choosing the next song at karaoke took time every time. Even though I had playlists created in Apple Music, when my turn came around I couldn't decide, and I'd end up picking the same few songs, which lacked novelty.
So I thought, why not eliminate the selection process entirely and just create an app that randomly draws one song—and I made an iOS app called "TuneDice." I published it on the App Store the other day.
https://apps.apple.com/jp/app/tunedice/id6804372799
It doesn't actually play songs or display lyrics. It's a simple tool that just tells you the song name.
The initial project name was "KaraokeRandomPicker." As I refined the requirements, I realized this wasn't specific to karaoke—it was just a generic feature to "randomly select one thing from a playlist." So I renamed it to "TuneDice" partway through. Since nothing had been released to the store yet, I was able to freely change the Bundle ID and folder names without hesitation.
The stack is Swift + SwiftUI + MusicKit for Swift, with Xcode project generation via XcodeGen (project.yml management). I went through almost the entire process from requirements definition to implementation with Claude Code.
I accumulated decisions in CLAUDE.md like "song source is either a playlist or library" and "sung history and NG list are managed with separate lifecycles," and refined the specifications while working backward from there to implementation. By resolving specification ambiguities on the documentation side first, I reduced rework during implementation.
Adding MusicKit capability made it impossible to build on a real device. Swift's MusicKit (import MusicKit, MusicAuthorization) doesn't require App ID capability or entitlements on the Developer Portal side. All that's needed is NSAppleMusicUsageDescription and runtime user authorization. Not knowing this, when I added the MusicKit capability, automatic signing failed due to invalid entitlements. After isolating the cause, removing it made the app build normally on the device.
Once denied, the permission dialog never appears again. Due to iOS specifications, once a user denies permission, that app can never show the system permission dialog again (this constraint is common across all apps). Not knowing this, I had added a "try again" button, which became a bug where after denial, the button appeared unresponsive because .denied was silently returned every time. I fixed it by checking the state with MusicAuthorization.currentStatus and switching the display: if undetermined, show the system dialog; if denied or restricted, show a button to open Settings. I also made it automatically re-check when returning from the Settings app.
NSAppleMusicUsageDescription was insufficient, so I rewrote it to explicitly state "why we're accessing this" and "we don't play or save"None of these were feature additions—they were all about the accuracy of explanations and user flows.
TuneDice is now available on the App Store. https://apps.apple.com/jp/app/tunedice/id6804372799
I'd be happy to receive feedback.
カラオケで次の曲を選ぶのに毎回時間がかかるのが地味にストレスだなーと思うことが多々ありました。Apple Musicにプレイリストは作ってあるのに、いざ順番が回ってくると選べず、結局いつもの数曲を選んでしまい面白みに欠ける。
それなら選ぶ作業自体をなくして、ランダムに1曲出すだけのアプリを作ればいいと思い、「TuneDice」というiOSアプリを作りました。先日App Storeに公開しています。
https://apps.apple.com/jp/app/tunedice/id6804372799
実際の再生や歌詞表示はやっていません。曲名を教えてくれるだけのシンプルなツールです。
最初のプロジェクト名は「KaraokeRandomPicker」でした。要件を詰めていくうちに、これはカラオケに限った話ではなく「プレイリストから何かひとつをランダムに選ぶ」だけの汎用機能だと気づき、途中で「TuneDice」にリネームしました。ストアには何も出していない段階だったので、Bundle IDやフォルダ名を含めて気兼ねなく変えられました。
Swift + SwiftUI + MusicKit for Swift、Xcodeプロジェクトの生成はXcodeGen(project.yml管理)という構成です。要件定義から実装まで、ほぼ全工程をClaude Codeと進めました。
CLAUDE.mdに「曲ソースはプレイリストかライブラリのどちらか」「歌った履歴とNGリストは別ライフサイクルで管理する」といった決定事項を書き溜めながら仕様を詰め、そこから逆算して実装を進めるやり方にしました。仕様の揺れを先にドキュメント側で潰しておくと、実装の手戻りは減りました。
MusicKit capabilityを付けたら実機ビルドできなくなりました。Swift向けMusicKit(import MusicKit、MusicAuthorization)は、Developer Portal側のApp ID capabilityやentitlementを必要としません。必要なのはNSAppleMusicUsageDescriptionと実行時のユーザー認可だけです。それを知らずにMusicKit capabilityを追加したところ、無効なentitlementのせいで自動署名が通らなくなりました。原因の切り分けたところ、外したら実機で普通に読めるようになりました。
一度拒否されると、二度と許可ダイアログは出ません。iOSの仕様上、ユーザーが一度パーミッションを拒否すると、そのアプリからはシステムの許可ダイアログを二度と出せません(どのアプリでも共通の制約です)。それを知らずに「もう一度試す」ボタンを付けていたら、拒否後は毎回黙って.deniedが返るだけでボタンが反応しないように見えるバグになっていました。MusicAuthorization.currentStatusで状態を見て、未確定ならシステムダイアログ、拒否・制限済みなら設定アプリを開くボタンに出し分け、設定アプリから戻ったタイミングで自動的に再チェックするようにして直しました。
NSAppleMusicUsageDescriptionの説明が薄いと指摘され、「何のためにアクセスするか」「再生や保存はしない」ことまで明記する文言に書き直したどれも機能追加ではなく、説明や導線の正確さを問われる指摘でした。
TuneDiceはApp Storeで公開中です。https://apps.apple.com/jp/app/tunedice/id6804372799
フィードバックいただけると嬉しいです。