I've been trying to get better at structured concurrency, so I took a stab at a function that collects all of the tracks from a library playlist. I think the key here is using the hasNextBatch property on MusicItemCollection. I'm far from on expert in this world, so I'm sure this code can be improved. In the meantime, here's what I came up with. It correctly returns the number of songs on playlists with more than 100 songs.
func getTracksFromPlaylist(name: String) async throws {
var request = MusicLibraryRequest<Playlist>.init()
request.filter(text: name)
let result = try! await request.response()
if let first = result.items.first {
let withTracks = try await first.with(.tracks)
guard let startingTracks = withTracks.tracks else {
return
}
try await getAllTracksFromPlaylist(startingTracks: startingTracks, group: nil)
}
}
func getAllTracksFromPlaylist(startingTracks: MusicItemCollection<Track>, group: ThrowingTaskGroup<[Track],Error>?) async throws {
//If the group didn't come in as nil, that means startingTracks has a next batch that needs to be fetched and processed
if var group = group {
if let currentSetToProcess = try await startingTracks.nextBatch() {
//Add the tracks from this batch to the group
group.addTask {
return Array(currentSetToProcess)
}
//If this set has a next batch, run the function again. Once currentSetToProcess.hasNextBatch returns false, the group will complete since it is not awaiting anything else.
if currentSetToProcess.hasNextBatch {
try await getAllTracksFromPlaylist(startingTracks: currentSetToProcess, group: group)
}
}
//If the group came in as nil, create the group and work through the first batch of tracks.
} else {
try await withThrowingTaskGroup(of: [Track].self, body: { group in
//The array to store the final set of tracks
var allTracks: [Track] = []
//Add the starting tracks to the group
group.addTask {
return Array(startingTracks)
}
//If there are more than 100 tracks on the playlist, this is true and means we need to loop through and get the other tracks.
if startingTracks.hasNextBatch {
try await getAllTracksFromPlaylist(startingTracks: startingTracks, group: group)
}
//As arrays of tracks are added to the group, append them to our allTracks array.
for try await tracks in group {
allTracks.append(contentsOf: tracks)
}
//Finally, when the group has returned all of the tracks, print the final amount.
print(allTracks.count)
})
}
}
Topic:
Media Technologies
SubTopic:
General
Tags: