WWDC Quick Look 💓 By SwiftGGTeam
Explore more content with MusicKit

Explore more content with MusicKit

元の動画を見る

ハイライト

MusicKit は 2022 年にその機能を大幅に拡張します。新しいキュレーターおよびラジオ番組タイプ、検索トップ結果と提案、ランキング API、オーディオ品質メタデータ (空間オーディオ / ロスレス)、そして最も重要なことに、完全なユーザー音楽ライブラリ リテラシーです。

主要内容

ディレクトリコンテンツの拡張

01:12

MusicKit は 2 つの新しいコンテンツ タイプを追加します。

キュレーター: Nike、Shazam、Beats by Dr. Dre などのブランドのキュレーター、および Apple 編集チーム。各キュレーターは、nameurlartworkそしてkindeditorialまたはexternal) 属性、およびplaylistsこの関係は、このキュレーターによって作成されたすべてのプレイリストを取得できます。

ラジオ番組: 「New Music Daily by Zane Lowe」など、playlists関係。

新しい逆の関係がプレイリスト タイプに追加されます。curatorそしてradioShow、プレイリストを作成者まで遡ることが簡単になります。

検索エクスペリエンスのアップグレード

03:37

上位の結果: 検索リクエストで設定includeTopResults = true、タイプ間で最も関連性の高い結果のリストを、関連性によって並べ替えて返します。

var searchRequest = MusicCatalogSearchRequest(
    term: "Hello",
    types: [Artist.self, Album.self, Song.self]
)
searchRequest.includeTopResults = true
let searchResponse = try await searchRequest.response()
print("\(searchResponse.topResults)")

重要なポイント:

  • topResultsすべてのリクエスト タイプの結果が 1 つのコレクションに混在して含まれます
  • 関連性によって並べ替えます。特定のタイプは気にしません
  • 検索インターフェースに適した最初の画面表示

提案: 音楽関連の自動補完の提案を提供します。

let request = MusicCatalogSearchSuggestionsRequest(term: "shaz")
let response = try await request.response()

重要なポイント:

  • それぞれの提案には、displayTerm(ディスプレイに適しています)searchTerm(実際の検索用)
  • ユーザーが提案を選択した後、次を使用します。searchTerm正式な検索を実行する

ランキング API

05:41

let request = MusicCatalogChartsRequest(
    kinds: [.dailyGlobalTop, .mostPlayed, .cityTop],
    types: [Song.self, Playlist.self]
)
let response = try await request.response()
print("\(response.playlistCharts.first)")

重要なポイント:

  • トップソング、トップアルバム、都市ランキング、毎日のグローバルトップ100をサポート
  • 音楽の種類によるフィルター
  • 組み込みのページングサポート、手動処理は不要MusicDataRequest

オーディオ品質メタデータ

06:58

MusicKit が公開されましたaudioVariants曲またはアルバムがサポートしているオーディオ形式を知るためのプロパティ:

let album =
let detailedAlbum = try await album.with(.audioVariants)
print("\(detailedAlbum.debugDescription)")

重要なポイント:

  • audioVariantsはいAudioVariant配列
  • 含むdolbyAtmos(空間オーディオ)、lossless(ロスレスオーディオ)など。
  • 新しいisAppleDigitalMaster最高品質のデジタル マスター テープを識別するブール値

現在再生中のオーディオ品質も取得できます。

@ObservedObject var musicPlayerState = ApplicationMusicPlayer.shared.state

var body: some View {
    if musicPlayerState.audioVariant == .dolbyAtmos {
        Image("dolby-atmos-badge")
    }
}

ユーザーデータベースへのアクセス

12:21

今年の最大のアップデート: アプリはユーザーの個人音楽ライブラリにアクセスできるようになりました。

MusicLibraryRequest: ネットワークを経由せずにデバイスからローカルにライブラリ コンテンツを読み込みます。

let request = MusicLibraryRequest<Playlist>()
let response = try await request.response()

重要なポイント:

  • 汎用パラメーターを使用して、要求されたタイプ (プレイリスト、アルバム、曲など) を指定します。
  • チェーンフィルタリングとソートをサポート
  • includeDownloadedContentOnly = trueダウンロードしたコンテンツのみを返却する

フィルタリングの例:

var request = MusicLibraryRequest<Album>()
request.filter(matching: \.isCompilation, equalTo: true)
request.filter(matching: \.genres, contains: danceGenre)
request.includeDownloadedContentOnly = true
let response = try await request.response()

MusicLibrarySectionedRequest: グループごとにライブラリ コンテンツを取得します。

var request = MusicLibrarySectionedRequest<Genre, Album>()
request.sortItems(by: \.artistName, ascending: true)
let response = try await request.response()

重要なポイント:

  • 最初の汎用パラメータはグループ化タイプ、2 番目はコンテンツ タイプです。
  • sortItemsコンテンツを並べ替えて、sortSectionsグループを並べ替える
  • 各グループがパスしますitemsプロパティはその下のコンテンツにアクセスします

データベース書き込み操作

22:01

MusicKit はユーザーの音楽ライブラリの変更をサポートするようになりました。

// 添加歌曲到播放列表
Task {
    try await MusicLibrary.shared.add(selectedTrack, to: playlist)
    isShowingPlaylistPicker = false
}

サポートされている操作は次のとおりです。

  • ライブラリにコンテンツを追加する
  • プレイリストの作成
  • プレイリストのメタデータとトラックリストを編集します
  • 既存のプレイリストに曲を追加

詳細

完全な検索インターフェイスの実装

struct MusicSearchView: View {
    @State private var searchTerm = ""
    @State private var suggestions: [MusicCatalogSearchSuggestion] = []
    @State private var topResults: MusicItemCollection<MusicCatalogSearchable> = []

    var body: some View {
        NavigationStack {
            List {
                // 搜索建议
                if !suggestions.isEmpty {
                    Section("Suggestions") {
                        ForEach(suggestions) { suggestion in
                            Button(suggestion.displayTerm) {
                                searchTerm = suggestion.searchTerm
                                performSearch()
                            }
                        }
                    }
                }

                // Top Results
                if !topResults.isEmpty {
                    Section("Top Results") {
                        ForEach(topResults) { item in
                            switch item {
                            case let song as Song:
                                SongRow(song: song)
                            case let album as Album:
                                AlbumRow(album: album)
                            case let artist as Artist:
                                ArtistRow(artist: artist)
                            default:
                                EmptyView()
                            }
                        }
                    }
                }
            }
            .searchable(text: $searchTerm)
            .onChange(of: searchTerm) { _ in
                loadSuggestions()
            }
            .onSubmit(of: .search) {
                performSearch()
            }
        }
    }

    func loadSuggestions() async {
        let request = MusicCatalogSearchSuggestionsRequest(term: searchTerm)
        let response = try? await request.response()
        suggestions = response?.suggestions ?? []
    }

    func performSearch() async {
        var request = MusicCatalogSearchRequest(
            term: searchTerm,
            types: [Song.self, Album.self, Artist.self]
        )
        request.includeTopResults = true
        let response = try? await request.response()
        topResults = response?.topResults ?? []
    }
}

重要なポイント:

  • MusicCatalogSearchSuggestionsRequestオートコンプリートの提案を提供する
  • includeTopResults = trueジャンル全体で最も関連性の高い結果を取得します
  • topResultsはいMusicCatalogSearchable型変換によって処理する必要がある型のコレクション

データベースプレイリスト表示

struct LibraryPlaylistsView: View {
    @State private var playlists: MusicItemCollection<Playlist> = []

    var body: some View {
        List {
            Section(header: Text("Library Playlists").fontWeight(.semibold)) {
                ForEach(playlists) { playlist in
                    PlaylistCell(playlist)
                }
            }
        }
        .task {
            await loadPlaylists()
        }
    }

    @MainActor
    private func loadPlaylists() async throws {
        let request = MusicLibraryRequest<Playlist>()
        let response = try await request.response()
        playlists = response.items
    }
}

重要なポイント:

  • MusicLibraryRequestネットワークトラフィックを消費せずにデバイスからローカルにロードします
  • 使用@MainActorUI の更新がメインスレッドで実行されるようにする
  • 返されましたAlbumSongタイプはディレクトリ要求によって返される構造と同じであり、機能も同じです。

フィルタリングされたデータベースクエリ

func fetchDanceCompilations() async throws -> MusicItemCollection<Album> {
    var request = MusicLibraryRequest<Album>()

    // 只返回合辑
    request.filter(matching: \.isCompilation, equalTo: true)

    // 只返回 Dance 类型
    let danceGenre = Genre(id: " dance", name: "Dance")
    request.filter(matching: \.genres, contains: danceGenre)

    // 只返回已下载的
    request.includeDownloadedContentOnly = true

    let response = try await request.response()
    return response.items
}

重要なポイント:

  • フィルター条件を連鎖的に組み合わせることができます
  • Xcode オートコンプリートは、現在のタイプでサポートされているキー パスのみを表示します
  • includeDownloadedContentOnlyオフラインシナリオのサポート

拡張属性をロードするときにソースを指定します

// 从目录加载专辑的曲目
let catalogTracks = try await album.with(.tracks)

// 从资料库加载同一专辑的曲目
let libraryTracks = try await album.with(.tracks, preferredSource: .library)

重要なポイント:

  • preferredSource: .library最初にユーザーデータベースからロードします
  • カタログのみまたはデータベースのみに存在する属性は影響を受けません。preferredSource影響
  • この機能は、元のアイテムがカタログ リクエストからのものであるかリポジトリ リクエストからのものであるかに関係なく使用できます。

重要ポイント

1.フィットネス アプリにおすすめの音楽を追加

  • 内容: ワークアウトの開始前に、ユーザーの個人的な推奨プレイリストと最近再生したコンテンツを表示します。
  • 実行する価値がある理由: MusicKitMusicPersonalRecommendationsRequestそしてMusicRecentlyPlayedRequest認証を自動的に処理し、1 行のコードでパーソナライズされたコンテンツを取得します
  • 開始方法: を使用しますMusicPersonalRecommendationsRequest()推奨事項を取得するには、次を使用しますMusicRecentlyPlayedRequest<Song>()最近再生した曲を取得する

2.ソーシャル アプリに音楽共有を追加

  • 内容: ユーザーが Apple Music カタログで曲を検索し、チャットやフィードで共有できるようにします
  • 実行する価値がある理由:MusicCatalogSearchRequestincludeTopResults検索エクスペリエンスをネイティブの Apple Music に近づけることで、ユーザーはアプリを離れることなく共有したい曲を見つけることができます
  • 開始方法: 統合された検索候補 + トップ結果、ユーザーは選択後に曲を取得できますurl共有するプロパティ

3. Focus/Pomodoro アプリに BGM を追加

  • やるべきこと: ユーザー ライブラリのコンテンツに基づいてフォーカス タイム プレイリストを作成します。
  • 実行する価値がある理由:MusicLibraryRequestタイプ、ダウンロードステータス、一致によってフィルタリングできますMusicLibrarySectionedRequestタイプごとにグループ化して表示
  • 開始方法: を使用しますMusicLibrarySectionedRequest<Genre, Song>()音楽の種類ごとにグループ化して、ユーザーが気分に応じて選択できるようにします

4.パーティー/イベント アプリに共同プレイリストを追加

  • 対処方法: イベント参加者が共有プレイリストに曲を追加できるようにします
  • やる価値がある理由: MusicKit がプレイリストの作成と曲の追加をサポートするようになり、「みんなで一緒に曲を選ぶ」機能を実現できます。
  • 開始方法: を使用しますMusicLibrary.shared.add(track, to: playlist)選択した曲をプレイリストに追加するには、次を使用します。MusicCatalogSearchRequest参加者に曲を検索してもらいます

関連セッション

コメント

GitHub Issues · utterances