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!
While building an Apple Music client, you’ll display artworks on almost every screen. Be it the home screen showing the album art, the music player, or the search results. Visuals are essential, and MusicKit provides an asynchronous image loading view called ArtworkImage
.
As the name suggests, it is a view that displays an image for an instance of Artwork
.
Artwork
Artwork
represents the artwork of the music item, whether it is an album art, a single or a playlist. It has many instance properties such as the maximum height and width available, the (average) background colour, and textual description for the image.
It also has an instance method url(width:height:)
that returns the URL to request the image asset for the particular width and height.
Now, you can either use the new AsyncImage
for asynchronously loading and displaying this artwork by providing the URL from the above instance method or use the ArtworkImage
.
ArtworkImage
ArtworkImage
makes it easier for us to display the image. You initialise the view in three ways by providing it with the artwork and -
- the height,
- the width,
- both height and width
init(_ artwork: Artwork, height: CGFloat)
init(_ artwork: Artwork, width: CGFloat)
init(_ artwork: Artwork, width: CGFloat, height: CGFloat)
It derives the URL of the image from the Artwork
. If you provide either height or width only, the other dimension is calculated as a proportional length according to the aspect ratio of the artwork. (Reference)
And for the placeholder, while the image is fetched, it uses the average background colour of the artwork using the backgroundColor
property to display the placeholder.
A trivial example from the sample project -
private var header: some View {
VStack {
if let artwork = album.artwork {
ArtworkImage(artwork, width: 320)
.cornerRadius(8)
}
Text(album.artistName)
.font(.title2.bold())
playButtonRow
}
}
Now, this works great on bigger devices. But when I tested it on my iPhone 7, the album artwork was cropped as we provided a hardcoded width. Because of this, the button also gets cropped. As the ArtworkImage
is not an Image
but a View
instead, we cannot apply resizable()
nor scaledToFit()
modifier.
I’m still figuring out a solution to this problem. As it is in a List
, the default inset style takes up space horizontally. One solution I came up with was using GeometryReader
. I provided the height in percentage if it is an iPhone and a hardcoded value if it is an iPad, so it doesn’t look comical on the huge screen.
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
var body: some View {
GeometryReader { geometry in
let width = horizontalSizeClass == .compact ? geometry.size.width * 0.75 : 350
List {
header(width: width)
.listRowBackground(Color.clear)
.buttonStyle(PlainButtonStyle())
// Rest of the content
}
}
}
And the header takes width as a parameter -
private func header(width: CGFloat) -> some View {
VStack {
if let artwork = album.artwork {
ArtworkImage(artwork, width: width)
.cornerRadius(8)
}
Text(album.artistName)
.font(.title2.bold())
}
}
This solves the UI problem on a small device like iPhone 7 or SE, with the image shrinking according to the screen’s width.
If you’ve a better solution, I would love to hear your thoughts! Message @rudrankriyam
Conclusion
ArtworkImage
is an excellent view for displaying the artwork of music items. If you want more control over the phase of the image, you can use ArtworkImage
. Using the network conditioner with a very bad network profile, Apple Music shows a blank placeholder. So, a placeholder with background colour is adequate for most use cases in Musadora.
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!