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 a Playlist Browser with Swift Refactoring Our Code Determining Playlists Programmatically

S B
S B
4,497 Points

Appending to playlistsArray (Detailed Logic)

Hi, I'm hoping to get a detailed understanding of the step by step logic of appending to playlistsArray. Here's my understanding (and associated questions) -

  1. At the beginning of the class, we create an empty array of type UIImageView: var playlistsArray: [UIImageView] = []
  2. We also have a stored property to display the main image. It's of value 'nil' at this point: @IBOutlet weak var playlistImageView0: UIImageView!
  3. The viewDidLoad() call is where it gets confusing for me. and this is where I lack understanding. I'm not sure how the append statement really interacts with the 'for' loop. Why we we appending playlistImageView0 to the array?

    override func viewDidLoad() { super.viewDidLoad()

    playlistsArray.append(playlistImageView0)
    
    for index in 0..<playlistsArray.count  {  
        let playlist = Playlist(index: index)
        let playlistImageView = playlistsArray[index]
    
        playlistImageView.image = playlist.icon
        playlistImageView.backgroundColor = playlist.backgroundColor
    }
    

    }

Can someone please break it down for me in detail?

Thanks!

2 Answers

Matthew Young
Matthew Young
5,133 Points

I'm relatively new to iOS development, but I believe I have a good grasp on what's going on in detail to explain it. I might not be 100% accurate with the terms I use, but I hope someone will correct me if I'm wrong.

Because playlistImageView0 is of type UIImageView, it is a visual element that is created (in our case, the Album artwork of the Playlist). If you were to append that view into the array created outside of the viewDidLoad method, it could be nil. The viewDidLoad method is run after all the visual elements are created so it's best to append playlistImageView0 within that method to ensure that it actually exists.

For now, the only image view that's created is playlistImageView0. In the future videos, you'll see the rest of the image views up to 6 in total. The "for-in" loop is set to go from 0 all the way to the playlistsArray.count, which for right now is 1. It's an open range meaning it's not including the number of playlistsArray.count, which again is currently 1. This is because arrays are indexed starting from 0 instead of 1. For example, if we have an array with 6 items in it, the last index would be 5 because the first index is 0, not 1.

Even though this loop currently only runs once, it's making it easy to implement more playlistImageViews without changing a lot of code.

Inside the loop...

The first statement is initializing the Playlist struct and passing through a single parameter, index. Index in this case is 0. Within the Playlist struct, this instance is grabbing the data from the dictionary created from before, specifically relating to the index of 0.

The second statement is creating a constant that's referring to what's stored at the current index value of the array playlistsArray, which is of type UIImageView. This is going to be playlistImageView0, which will allow the next two statements to alter the properties of it.

The third statement is utilizing the "image" property of the UIImageView superclass to assign an image within the current playlistImageView. The image assigned is found within the "icon" property of the "playlist" instance of the "Playlist" struct. In other words, if you look within the Playlist.swift file, you'll see a property you created there called "icon" which is pointing to an image stored within the dictionary. We are using this image to assign to the playlistImageView so we can see the Album artwork.

The fourth statement is similar to the third statement, except we are getting the color to be used as the background for the current playlistImageView.

Once more playlistImageViews are added to the playlistsArray, this loop will go through each one and pull the data so that each Album artwork is presented on the main screen of the App.

I hope this helps! Feel free to ask if you need further clarification.

S B
S B
4,497 Points

Hey Matthew, this was great. I appreciate the detailed answer. I watched the rest of the videos, and I guess what I'm still not fully grasping is what happens when the viewDidLoad method begins and when the following line is executed:

playlistsArray += [playlistImageView0, playlistImageView1, playlistImageView3, ...]

At this point, does the playlistArray just contain a bunch of 'nil' values?

Also, when the for loop is executed, I get how we're going through each index item which exists (so in this example, 0-5), calling the Playlist struct for that particular index item, etc.

However, when the following line is run for the first time (index: 0), how exactly does the array change?

playlistImageView.image = playlist.icon
playlistImageView.backgroundColor = playlist.backgroundColor

In the first cycle through the loop, does the array look like this?

[["icon": "coffee.pdf", "backgroundColor": ["red": 255, "green": 204, "blue": 51, "alpha": 1.0], nil, nil, nil, nil]

What if we wanted to pull the title and description vs. the icon and background colour.

What type would the stored properties in the View Controller need to be? And would the for loop now look like this? ...

for index in 0..<playlistsArray.count  {
    let playlist = Playlist(index: index)
    let playlistImageView = playlistsArray[index]

    playlistImageView.text = playlist.title
    playlistImageView.text = playlist.description
}

I apologize for the level of detail I'm getting into, but it's unsettling not to know the above. Thanks!

Matthew Young
Matthew Young
5,133 Points

Once the viewDidLoad method is accessed, all the visual elements are loaded. Therefore, your array contains all the UIImageView instances. These instances are connected to your storyboard through the IBOutlet. You're not really modifying the array within the for-in loop, you're just using it to access and change the individual properties of each playlistImageView. Once the loop is finished, the playlistsArray still contains the same elements as before.

The loop isn't creating a whole new dictionary, we're accessing the properties of each playlistImageView and assigning them data from our dictionary, which is accessed using the Playlist struct instance.

The purpose of the for-in loop is just easily accessing the properties of each imageView in a concise fashion and adhering to the DRY principle ("Don't Repeat Yourself"). If you didn't have the for-in loop, your code would essentially be this:

let playlist0 = Playlist(index: 0)
let playlistImageView0 = playlistsArray[0]

playlistImageView0.image = playlist0.icon
playlistImageView0.backgroundColor = playlist.backgroundColor

let playlist1 = Playlist(index: 1)
let playlistImageView1 = playlistsArray[1]

playlistImageView1.image = playlist1.icon
playlistImageView1.backgroundColor = playlist1.backgroundColor

let playlist2 = Playlist(index: 2)
let playlistImageView2 = playlistsArray[2]

playlistImageView2.image = playlist2.icon
playlistImageView2.backgroundColor = playlist2.backgroundColor

...and so on until all the playlistImageViews are accessed and their properties modified. As you can see, this is a lengthy bit of code that is nicely avoided by using the for-in loop. Imagine if you had 1000 playlistImageViews that needed to be updated? The for-in loop remains the same length and will still access and modify them all.

As far as accessing the "title" and "description" properties in your example, there is no "title" property for an instance of UIImageView and the "description" property is read-only. The "description" property only creates a text-representation of the object within the UIImageView instance. Even if there was a "text" property associated with UIImageView, your example would first set the title to the data found in "playlist.title" and then get rewritten in the next statement to the data in "playlist.description".

I think understanding that you're not creating an additional dictionary with your playlistsArray should clear up your confusion, but if not, I can try and come up with another example to try and illustrate what's going on.

S B
S B
4,497 Points

Matthew, this was a perfect actually! Essentially, this is what I got from your response...

The purpose of appending the UIImageView's to the array is to set the "Image" and "Background" properties of each UIImageView. We did this manually before in the Attributes Inspector, by modifying the "Image" and "Background" properties for each UIImageView.

At the time when we append the UIImageView's to the array, the 'placeholder' image and the 'default' background are still set. Once the for loop is run, we are able to replace the 'placeholder' image and 'default' background for each of the UIImageView's on the screen with the respective values in MusicLibrary.

A-HA! Computers are Brilliant!

Thank you for helping me understand this Matthew...breakthroughs like this are really exciting. I hope this helps others who are also stuck with this concept.

Matthew Young
Matthew Young
5,133 Points

Sounds like you have a great understanding of it now! I'm glad I was able to help. I agree that breakthroughs in learning concepts are a wonderful feeling too.

I've found the forums are an excellent way to help solidify different concepts. So basically help others with problems like I did with yours and you'll find a better understanding of the concepts as well!

S B
S B
4,497 Points

Awesome, and I'll definitely do that....Circle of Life.

Cheers Matthew! Thanks again.

The playlistArray is an array, which holds multiple values. Think of it as a box where you can store multiple stuff(values). If you want to do something with each item in the array, aka, iterate through each item in the array, you can do it the long way, which means writing the "let playlistImageView = playlistsArray[0]", "let playlistImageView = playlistsArray[1]", "let playlistImageView = playlistsArray[2]"... and so on. The issue with this way is that it is static, meaning that you have to declare each item in the array individually. The recommended way, which you will soon be familiar with, is using the for ... in loop, OR the for (i=0, i<arrayname.count, i++) loop. This way, the computer will iterate through EACH item in the array, e.g playlistArray[0], playlistArray[1], playlistArray[2]... until the last item in the array (.count). So no matter what, you will go through through each item in the for....in loop. For...in loops are very very useful for iterating through items in an array. In a real life example, I just used a for...in loop to iterate through each item in an UI image array, which was a photo album, so I could upload each one individually to a database. Hope that clarifies.