UICollectionView Tutorial: Getting Started | raywenderlich.com

In this tutorial, you’ll get hands-on experience with UICollectionView by creating your own grid-based photo browsing app.

This is a companion discussion topic for the original entry at https://www.raywenderlich.com/9334-uicollectionview-tutorial-getting-started

func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow

return CGSize(width: widthPerItem, height: widthPerItem)


This code block not executing as desired as some times instead of itemsPerRow it returns (itemsPerRow - 1) columns in a row (vertical scrolling)
We need to do something like (widthPerItem - K) where K value is only able to find through hit & trials to get exact itemsPerRow
Any exact solution for that ?

@wviper3 Can you please help with this when you get a chance? Thank you - much appreciated! :]

Question about the activity indicator as a subView in the uiTextField. Is adding a new instance of an indicator view as a subview and then removing it from the superview the most efficient method? Wouldn’t it be more efficient to subclass uiTextField and then have the appropriate logic to active/inactive/hide/unhide the activity view? Just wondering.

@wviper3 Do you have any feedback about this? Thank you - much appreciated! :]

If you’re going to be adding the subview back to the superview soon after it’s removed, its probably best to use the isHidden property. Likewise if you have many subviews coming and going or one that will be gone for a long period of time, you should remove it.

In this case either would work. This is the code required to use isHidden inside the Text Field Delegate:

  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    // 1
    var activityIndicator = view.subviews.compactMap({$0 as? UIActivityIndicatorView}).first
    if activityIndicator == nil {
      activityIndicator = UIActivityIndicatorView(style: .gray)
      activityIndicator!.frame = textField.bounds
    } else {
      activityIndicator!.isHidden = false
    flickr.searchFlickr(for: textField.text!) { searchResults in
      activityIndicator!.isHidden = true

Take a look at this stack overflow thread for more information.

Hello, and thank you for the wonderful tutorial. I am new to Swift and learning UICollectionViews for the first time.

Can you explain why the functions are created as extensions?

Thank you Kindly!

Hi Ryan,

Thanks for reading, and welcome to the forums! We usually group functions into extensions when those functions are part of a protocol. It keeps your code organised and helps you identify parts than could maybe form a separate object or type later on.

Thank you, Richard. This makes sense and helps a lot. This UICollectionsView tutorial is wonderful - thank you and the team for sharing!

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!