Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build An iTunes Search App Downloading Album Artwork Wrapping Up

Marcos Reboucas
Marcos Reboucas
12,890 Points

What's best practice to get the artwork to show in AlbumDetailController?

I'm wondering what's the correct way to get the album artwork to show in AlbumDetailController. As we already have the image in the AlbumListController I guess it'd be not a good idea to download the image again because it's an expensive process.

So I created an UIImage stored property in AlbumDetailController and just passed it forward in AlbumListController prepareForSegue, then I updated artworkView.image inside func configure(with album: Album):

// in AlbumListController let albumCover: UIImage = selectedAlbum.artwork! albumDetailController.albumCover = albumCover

// in AlbumDetailController func configure(with album: Album) {

    let viewModel = AlbumDetailViewModel(album: album)

    if let albumCover = albumCover {
        artworkView.image = albumCover
    }

    albumTitleLabel.text = viewModel.title
    albumGenreLabel.text = viewModel.genre
    albumReleaseDateLabel.text = viewModel.releaseDate
}

I recognize this approach is ugly despite it works. But since I'm not able to use AlbumDetailViewModel to update the artwork, because at this time we have just updated the Album with new Song data and it has no artwork, what would be a better way to do this?

In the end I used a similar approach to yourself, I would also be interested as to how you approach this using best proactively we might be fresh out of luck Marcos

4 Answers

Douglas Ferreira
Douglas Ferreira
9,028 Points

The previous solutions didn't work for me, then the solution I found was:

  1. Create an stored property of type UIImage in "AlbumDetailController.swift". You can assign it as an optional one.
  2. In "AlbumListController.swift" you assign the artwork of the selected album to this property in "AlbumDetailController.swift".
  3. Then you can assign the image of the artwork to its own outlet.

In code:

AlbumDetailController.swfit

var artworkImage: UIImage?

// This line goes in the configure method
artworkView.image = artworkImage

AlbumListController.swift

// This line goes in prepare for segue method after assign the destination
albumDetailController.artworkImage = selectedAlbum.artwork
Qasa Lee
Qasa Lee
18,916 Points

I came up with a really simple way as below:

// in "AlbumListController" all the way down to "prepare(for segue...)" method:
client.lookupAlbum(withAlbumID: selectedAlbum.id) { (album, error) in
                        albumDetailController.artworkView.image = selectedAlbum.artwork
                        albumDetailController.album = album
                    }

I suppose the logic going on here is pretty straightforward.

Patrick Duhamel
Patrick Duhamel
5,786 Points

In AlbumListController, when an album is selected, the function prepare(for segue...) is called and a new object album is created from client.lookupAlbum, which doesn't have the artwork information because it's only looking for information on the selected album. To pass the artwork already downloaded, we need to pass the artwork from the object selectedAlbum to the new object album before sending it to the albumDetailController:

client.lookupAlbum(withId: selectedAlbum.id) { album, error in
   album?.artwork = selectedAlbum.artwork
   albumDetailController.album = album
}

I preserved some other keys too:

if selectedAlbum.artworkState == .downloaded {
    album?.artwork = selectedAlbum.artwork
    album?.artworkState = .downloaded
}

What I did, was that I added the the album art of the selectedAlbum (selectedAlbum.artwork) to album?.artwork in the AlbumListController. In AlbumDetailController, in the configure() method, I then set the artworkView.image to viewModel.artwork.

Ofcourse for this to work we need to add an artwork stored property of type UIImage? (remember to add UIKit) to AlbumDetailViewModel, and then init the stored property to album.artwork.

This is clearly not the optimal solution since loading the songs now hangs until the image has been loaded. (I don't know why though.)

Qasa Lee
Qasa Lee
18,916 Points

Buddy, you can simply set "album.artwork" to "artworkView.image" in AlbumDetailController's "configure()" method as below:

func configure(with album: Album) {
        let viewModel = AlbumDetailViewModel(album: album)

        //        Add implemention for artworkView
        artworkView.image = album.artwork

        albumTitleLabel.text = viewModel.title
        albumGenreLabel.text = viewModel.genre
        albumReleaseDateLabel.text = viewModel.releaseDate
    }

Since you've already done "album?.artwork = selectedAlbum.artwork" in the "prepare(for segue...)"(in the AlbumListController), which means there's no need to use "viewModel'-way to set "artworkView.image".