MusicKitで最近再生した曲の完全な情報を取得する方法
概要
MusicKit
フレームワークには、ユーザーが Apple Music で最近聴いた曲やミュージックビデオを取得できる
MusicRecentlyPlayedRequest
というAPIが存在します。
本記事では、その 基本的な使い方 と 完全な楽曲情報を取得する方法(ハイドレーション) について解説します。
公式ドキュメント:
MusicRecentlyPlayedRequest | Apple Developer Documentation
基本的な使い方
以下は、ユーザーの許可を得てから最近再生した楽曲リストを取得し、レスポンスをそのまま print
する最もシンプルな例です。
import MusicKit
func fetchAndPrintRecentlyPlayed() async throws {
// ユーザーにApple Musicへのアクセス許可をリクエストする
let status = await MusicAuthorization.request()
guard status == .authorized else {
print("Apple Musicへのアクセスが許可されていません。")
return
}
// MusicRecentlyPlayedRequest<...> の部分で取得するデータ型を指定
var request = MusicRecentlyPlayedRequest<Song>()
// 取得件数の上限を設定 (最大値は30)
request.limit = 25
// 取得開始位置(ページネーション用)
request.offset = 0
// リクエストを実行してレスポンスを取得
let response = try await request.response()
print(response)
}
<T>
に指定できるデータ型一覧
MusicRecentlyPlayedRequest<T>
の <T>
には、取得したいデータの型を指定します。
型 | 説明 | ドキュメント |
---|---|---|
Song |
個々の楽曲(ミュージックビデオは含まない)を取得 | developer.apple.com |
MusicVideo |
ミュージックビデオの履歴を取得 | developer.apple.com |
Track |
楽曲(Song )とミュージックビデオ(MusicVideo )が混在した履歴を取得 |
developer.apple.com |
Station |
ラジオステーションの再生履歴を取得 | developer.apple.com |
RecentlyPlayedMusicItem |
アルバム・プレイリストなどの「コンテナ」履歴を軽量に取得 | developer.apple.com |
レスポンスの特徴
上記の基本関数を実行しても、すべてのプロパティが返り値に含まれるわけではありません。
先ほどのswiftコードの実行例
MusicRecentlyPlayedResponse<Song>(
items: [
Song(id: "1821113648", title: "Episodes Intro", artistName: "Gucci Mane"),
Song(id: "1846237407", title: "Fa Sure", artistName: "Money Man"),
Song(id: "1846236924", title: "No Spaghetti", artistName: "Money Man"),
Song(id: "1674326497", title: "Rasen in Okinawa", artistName: "Awich, Tsubaki, OZworld & CHICO CARLITO"),
Song(id: "1834391398", title: "Hottoke", artistName: "Mukade"),
Song(id: "i.dlvqRdJUzq3ozeK", title: "Champion Road", artistName: "BAD HOP"),
Song(id: "1479862418", title: "Swing", artistName: "TOCCHI"),
Song(id: "1526343785", title: "Tao", artistName: "Tsubaki"),
Song(id: "i.9oJNbRBSPeo7Pgm", title: "Ainomamani (feat. Tsubaki)", artistName: "BASI"),
Song(id: "1793303080", title: "Namuabidabutsu", artistName: "Tsubaki"),
Song(id: "1472001765", title: "Merry Go Round (feat. BASI, Tsubaki, VIGORMAN & WILYWNKA)", artistName: "GeG"),
Song(id: "1367480255", title: "Feel (feat. IO, Tubaki & Yo-Sea)", artistName: "DJ CHARI & DJ TATSUKI"),
Song(id: "i.aJGY1m9T3PaK3dQ", title: "Moon (feat. Bon Iver)", artistName: "Daniel Caesar"),
Song(id: "1836082423", title: "BAD LOVE", artistName: "HANA"),
Song(id: "i.NJv0A49fl8zBlKQ", title: "Blue Jeans", artistName: "HANA"),
Song(id: "1729761357", title: "Last Party Never End (feat. Tiji Jojo, YZERR, Vingo & Yellow Pato)", artistName: "BAD HOP")
]
)
ドキュメントを見るとSongには他のプロパティも含まれていますが、デフォルトではオプショナルになっていないフィールドのみが返り値に含まれます。
これは 「遅延読み込み (lazy loading)」 のためです。
初回のレスポンスではリスト表示に必要な最低限のデータしか返されません。
duration
, albums
, artists
などの詳細情報を取得するには、
.with()
メソッドを使用して非同期的に追加取得(データハイドレーション)を行います。
完全な情報を取得する方法(ハイドレーション)
複数の曲を効率よくハイドレーションするには、
withThrowingTaskGroup
を用いた並行処理が有効です。
import MusicKit
func fetchAndPrintRecentlyPlayedWithDetails() async throws {
// Apple Musicアクセス権の確認
let status = await MusicAuthorization.request()
guard status == .authorized else {
print("Apple Musicへのアクセスが許可されていません。")
return
}
// 1. 再生履歴(サマリオブジェクト)を取得
var request = MusicRecentlyPlayedRequest<Song>()
request.limit = 25
let response = try await request.response()
// 2. 各楽曲の完全な情報を並行して取得(データハイドレーション)
let detailedSongs = try await withThrowingTaskGroup(of: Song.self) { group in
var songs: [Song] = []
songs.reserveCapacity(response.items.count)
// 取得したいプロパティのリスト
let propertiesToLoad: [PartialMusicAsyncProperty<Song>] = [
.artists,
.albums,
.duration,
.genreNames,
.composerName,
.url
]
// 各サマリオブジェクトに対して詳細取得タスクを追加
for summarySong in response.items {
group.addTask {
try await summarySong.with(propertiesToLoad)
}
}
// 全タスク完了後、結果をまとめる
for try await detailedSong in group {
songs.append(detailedSong)
}
return songs
}
// 3. 完全な情報を出力
print("--- 取得した全楽曲の詳細情報 ---")
print(detailedSongs)
print("---------------------------")
}
propertiesToLoad
に指定できる値
propertiesToLoad
の部分で、ドキュメントページでオプショナルになっているフィールド名をセットするとその情報を含めた状態でのresponseを取得できます。
先ほどのswiftコードの出力例
.artists
と .albums
を指定してハイドレーションした場合、
以下のようにネストされた完全な Song
オブジェクトが取得されます。
--- 取得した全楽曲の詳細情報 ---
[
Song(
id: "1846237407",
title: "Fa Sure",
hasLyrics: false,
isrc: "USUYG1765874",
releaseDate: "2025-10-17",
trackNumber: 2,
url: "https://music.apple.com/jp/album/fa-sure/1846236922?i=1846237407&l=en-US",
albums: [
Album(
id: "1846236922",
title: "Money Man Essentials",
// ... Albumの他のプロパティ
)
],
artists: [
Artist(
id: "689731655",
name: "Money Man",
// ... Artistの他のプロパティ
)
]
),
// ... 他の完全なSongオブジェクト
]
---------------------------
🎉 おしまい!