Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Yesterday, while working on the queue screen on the Sonar app, I encountered a problem where some of the artworks return nil values from the entries of the player. This is frustrating, especially when I want to display the artwork in a visually appealing way. In this blog post, I explore how to handle nil artworks and a workaround to show the artwork from the queue.

When you find some of the artworks in the queue return nil values, it results in blank spaces or placeholders in the app, which can be unappealing to users.

Displaying Artwork from Queue Entry

In a typical view, I display the artwork for an entry from the queue like this:

struct QueueArtworkView: View {
  var entry: MusicPlayer.Queue.Entry
  var body: some View {
    Group {
      if let artwork = entry.artwork {
        ArtworkImage(artwork, width: 120, height: 120)
          .cornerRadius(12)
      }
    }
  }
}

This code checks if the artwork exists and displays it if it does. However, if the artwork is nil, it won’t display anything.

Fetching the Data of Artwork

If the artwork is a different format for some reason, I can use the url(width:height:) method on the artwork to fetch the image and update an UIImage instance instead:

struct QueueArtworkView: View {
  @State private var artworkImage: UIImage?

  var body: some View {
    Image(uiImage: artworkImage)
      .cornerRadius(12)
  }
}

extension QueueArtworkView {
  func getArtworkImage() async {
    do {
      if let url = entry.artwork?.url(width: 120, height: 120) {
        let (data, _) = try await URLSession.shared.data(from: url)
        self.artworkImage = UIImage(data: data)
      }
    } catch {
      debugPrint("Error getting artwork image for song: ", entry.title ?? "")
    }
  }
}

Workaround for Nil Artwork

In my case though, the artwork itself is nil, so I cannot get the URL of it and do a network request to fetch it. There is a workaround for this issue. For the songs that have artwork equal to nil, I can try to fetch a full version of the song, which will have an artwork. I can use any random property on the song instance to do that.

Here’s an example of how you can modify the code to handle nil artworks and fetch a full version of the song instead:

struct QueueArtworkView: View {
  var entry: MusicPlayer.Queue.Entry
  @State private var artworkImage: UIImage?
  var body: some View {
    Group {
      if let artwork = entry.artwork {
        ArtworkImage(artwork, width: 120, height: 120)
          .cornerRadius(12)
      } else if let artworkImage {
        Image(uiImage: artworkImage)
          .cornerRadius(12)
      }
    }
    .task {
      if entry.artwork == nil {
        await getArtworkImage()
      }
    }
  }
}

extension QueueArtworkView {
  func getArtworkImage() async {
    do {
      if case let .song(song) = entry.item, let url = try await song.with(.artistURL).artwork?.url(width: 120, height: 120) {
        let (data, _) = try await URLSession.shared.data(from: url)
        self.artworkImage = UIImage(data: data)
      }
    } catch {
      debugPrint("Error getting artwork image for song: ", entry.title ?? "")
    }
  }
}

In this code, I first check if the artwork exists. If it does, I display it. If it does nott, I fetch a full version of the song using the getArtworkImage function.

The getArtworkImage function uses the song.with(.artistURL) property to fetch a full version of the song. It then checks if the artwork URL exists and fetches the image data from the URL. Finally, it sets the artworkImage to the UIImage created from the data.

Conclusion

While this workaround can solve the issue of nil artworks, it can be improved using background fetching or caching the image. By fetching the artwork in the background, we can avoid blocking the main thread and improve the user experience. Caching the image can also help reduce network usage and improve the app’s performance.

Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Written by

Rudrank Riyam

Hi, my name is Rudrank. I create apps for Apple Platforms while listening to music all day and night. Author of "Exploring MusicKit". Apple WWDC 2019 scholarship winner.