Post

Replies

Boosts

Views

Activity

Reply to Music Kit HTML Embeds move an 490 px and below
Thanks DTS Engineer! Sadly, you folks have gone anonymous. No more crying to @JoeKun when I need him 😄 I have filed the bug report (FB15454154), but to be frank, I've filed some that have gone without a response for years. Others, I've noticed have actually been fixed quietly, and yet the Radar remains open. Just sayin'... Important to note is that this happens on your website, so "how I'm calling Music Kit" isn't applicable. There's something sketchy with the iframe implementation.
Oct ’24
Reply to Editing a Library Playlist (MusicKit: iOS 16 beta)
@JoeKun This bug is back again. Long story, short: I redeployed an app that hasn't changed code-wise. This line causes stops the function that it's in and throws no error. It also does not edit the playlist. try await MusicLibrary.shared.edit(targetPlaylist, items: items) The only things that have changed, I imagine, are related to new releases of software since WWDC 2023.
Jun ’23
Reply to Editing a Library Playlist (MusicKit: iOS 16 beta)
Hi @CPDigitalDarkroom, The trick to using .edit, is that you need provide an array (i.e. sequence) of .items. In the below, playlist is the actual playlist retrieved using MusicLibraryRequest, and items is an array/sequence of tracks. With .edit, items replaces all tracks in the playlist, so you need to be sure you're providing what you want to be in the playlist with items. let updatedPlaylist = try await MusicLibrary.shared.edit(playlist, items: items) If all tracks are being removed from your playlist, using .edit, I would check to make sure that you are supplying and actual array of items. If that's empty, then you'll wind up with an empty playlist. I hope that makes sense. If not, feel free to ask, and I'll do my best to help you out.
Jul ’22
Reply to MusicLibraryRequest to get all tracks from a playlist (iOS 16 beta)
HI @david-apple, Thanks for the pro advice! In my initial post on this thread, I mentioned getting all tracks from a playlist with over 100 tracks. Sorry, I know that post was a bit wordy, so it's easy to overlook that point. My findings are that .with, in this scenario, has a cap of 100 tracks, which is why I started looking at ways to get more than 100. This is an edge case, but I do need to accommodate for this scenario. I found that .nextBatch() allows for a limit of 300, which is nice and results in less calls. If I'm mistaken, and that is entirely possible, kindly advise. PS: Kindly note that using .preferredSource: .library or omitting that parameter results in the .edit method failing, as I've mentioned here. I'm loving the new iOS 16 stuff for MusicKit and hope my inputs help.
Jun ’22
Reply to MusicLibraryRequest to get all tracks from a playlist (iOS 16 beta)
Thanks for the feedback, @JoeKun! I always appreciate your help 😊 My usage for this is not for displaying in the UI, but for various other things. For example, if I want to use the following to update the tracks in a playlist, where items is all existing tracks in the playlist plus some new tracks or minus a specific subset. let updatedPlaylist = try await MusicLibrary.shared.edit(playlist, items: items) At present, I don't see a way to use the .edit method otherwise. I think I need all those items ahead of time. Adding tracks could be done without the use of .edit, using a loop and multiple .adds; it's the removal of tracks that seems tricky to me. Of course, I could be missing something. If that's the case, I'd love to hear a better way to achieve this.
Jun ’22
Reply to MusicLibraryRequest to get all tracks from a playlist (iOS 16 beta)
Hi @talkingsmall, Thanks much for your thorough and thoughtful reply. I was unaware (or blanking on) of the .hasNextBatch on MusicItemCollection for some reason. I appreciate you bringing that to my attention, as it helped me come up with a solution (extra logging added for clarity): @available(iOS 16.0, *) func getAllTracksFromPlaylistId(id: MusicItemID) async throws -> [Track]? {     func getAllTracks(tracks: MusicItemCollection<Track>) async throws -> [Track]? {         var hasNextBatch = true         var tracksToReturn = tracks.compactMap{$0}         var currentTrackCollection = tracks         Logger.log(.info, "Initial track count: \(tracks.count)")         do {             while hasNextBatch == true {                 if let nextBatchCollection = try await currentTrackCollection.nextBatch(limit: 300) { // 300 is max here tracksToReturn = tracksToReturn + nextBatchCollection.compactMap{$0}                     Logger.log(.info, "Fetched \(nextBatchCollection.count) track(s) from next batch")                     Logger.log(.info, "Current track subtotal: \(tracksToReturn.count)")                     if nextBatchCollection.hasNextBatch {                         Logger.log(.info, "nextBatchCollection has nextBatch.  Continuing while loop...")                         currentTrackCollection = nextBatchCollection                     } else {                         Logger.log(.info, "nextBatchCollection has no nextBatch. Breaking from while loop")                         hasNextBatch = false                     }                 } else {                     Logger.log(.info, "No results from nextBatch()! Breaking from while loop")                     hasNextBatch = false                 }             }             if tracksToReturn.count > 0 {                 Logger.log(.info, "Returning \(tracksToReturn.count) track(s)")                 return tracksToReturn             } else {                 Logger.log(.info, "tracksToReturn is empty!")                 return nil             }         } catch {             Logger.log(.error, "Could not get next batches!")         }         return nil     }     do {         var request = MusicLibraryRequest<MusicKit.Playlist>()         request.filter(matching: \.id, equalTo: id)         let response = try await request.response()         if let playlist = response.items.first {             if let tracks = try await playlist.with(.tracks, preferredSource: .catalog).tracks {                 if let allTracks = try await getAllTracks(tracks: tracks) {                     Logger.log(.success, "\(playlist.name) has \(allTracks.count) tracks")                     return allTracks                 } else {                     Logger.log(.fire, "Could not fetch any tracks for \(playlist.name)")                 }             } else {                 Logger.log(.fire, "With tracks on \(playlist.name) returns nil for tracks")             }         } else {             Logger.log(.warning, "Could not find playlist with id: \(id)!")         }     } catch {         Logger.log(.error, "Could not: \(error)")     }     return nil } It might be noticed that I've not attempted any concurrency, instead using a while loop to fetch all tracks, serially, in batches. The reason for this is because, I don't think it speeds things up at all, because I don't think we can't use .nextBatch() in parallel async calls. In the Apple Music API MusicDataRequest example in my initial post, I can get the total number of tracks in a playlist by looking at the meta.total value and then leverage async calls, using the right offsets to get "next batch" tracks in parallel calls. This significantly improves the speed on playlists with a large number of tracks. I'm not sure that a MusicItemCollection can provide us with something equivalent to meta.total, and it doesn't appear that .nextBatch() takes an offset argument. So I'm not sure how to speed things up better than what I've come up with here. Of course, it's highly probable that I am mistaken about that. That said, I can now get all tracks using MusicLibraryRequest to fetch a playlist and using .with on the resultant MusicItemCollection<Playlist>, followed by using .hasNextBatch and .nextBatch(), which is what I was looking for. Thanks again, @talkingsmall!
Jun ’22
Reply to Editing a Library Playlist (MusicKit: iOS 16 beta)
Hi @JoeKun & @david-apple, I have found that if I retrieve the items by using preferredSource: .catalog in the .with, per the below, that the MusicLibrary edit does not crash. excluding preferredSource or using preferredSource: .library in the .with will cause the crash. if let tracksToAdd = try await playlist.with(.tracks, preferredSource: .catalog).tracks {    // add tracks to target playlist } I've updated the ticket accordingly. Also, as a side note, it seems that .with only returns a max of 100 tracks. I'll keep testing and raise under separate cover, if I can't figure that out.
Jun ’22