0

I'm interested in creating a view that contains multiple features that users can scroll down and see i.e. pictures, description, comments, carousels etc. I am aware that the UICollectionView is able to provide this type of layout. I initially thought UITableViews would be the best approach.

I have looked at several tutorials and GitHub repos but majority of them just use a UICollectionView in a standard grid layout. I've also looked at IGListKit used by Instagram and some the tutorials linked to it.

I'm aiming to get something like the KitchenStories app:

enter image description here

I was wondering if someone could advice me in terms of the direction and approach best for this.

Chace
  • 561
  • 10
  • 28

1 Answers1

1

Don't try to do too much with any single view, even a UICollectionView.

The screen you've shown has a UITabBarController manage its top-level arrangement. The currently selected tab (“Home”) has a UINavigationController managing its content.

On the top of the navigation stack is, probably, a collection view or a table view. Either could be used here because the elements are visually laid out as screen-width rows in a stack. A table view is simpler because then you don't have to worry about setting up the layout.

The table view has several visible rows, each different:

  • The title/image row (“Easy seafood paella”)
  • The ratings row
  • The export row (hearts / save / share)
  • The comments row
  • The creator row (I assume, since it looks like it's probably a headshot and a name)

And there are probably even more unique rows out of view.

In your storyboard, you can design each of these rows as a prototype row in the table view controller's scene. Or you can design the table view with static content rows, which is easier if you won't need to change the order of the rows or duplicate any rows at run time.

“But Rob,” you say, “I can't fit all those rows into the table view in my storyboard!” Make the storyboard scene taller. UIKit will resize it at run time to fit the device screen.

In each row, drag in and arrange whatever subviews you need for that row's data. For example, the title/image row needs a UIImageView and a UILabel. The ratings row needs a label, probably a custom view to display and edit the stars, and perhaps a stack view for layout.

For each row, you'll need a separate subclass of UITableViewCell with outlets to that row's views. To pass the data to each cell for display, make each cell conform to a protocol:

protocol RecipeUsing {
    var recipe: Recipe? { get set }
}

Then, in your table view controller, you set it like this if you're using static content:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAt: indexPath)
        if let user = cell as? RecipeUsing {
            user.recipe = recipe
        }
        return cell
    }

You'll need a RecipeTitleImageCell with outlets to the UIImageView and UILabel. Something like this:

class RecipeTitleImageCell: UITableViewCell, RecipeUsing {

    @IBOutlet var label: UILabel!

    // UITableViewCell has an imageView property that's not an outlet 
    @IBOutlet var myImageView: UIImageView!

    var recipe: Recipe? {
        didSet {
            guard let recipe = recipe else { return }
            label.text = recipe.title
            myImageView.image = recipe.image
        }
    }
}

And for the ratings row, you'll want something like this:

class RecipeRatingsCell: UITableViewCell, RecipeUsing {
    @IBOutlet var ratingControl: RatingControl!
    @IBOutlet var label: UILabel!

    var recipe: Recipe? {
        didSet {
            guard let recipe = recipe else { return }
            ratingControl.rating = recipe.ratings.reduce(0, +) / recipe.Double(ratings.count)

            if ratings.count < 5 { label.text = "Too few ratings" }
            else { label.text = "\(ratings.count) ratings" }
        }
    }
}
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Thank you for this answer as it has given me a better idea of ways to approach my objective. I have actually looked at this post: https://medium.com/ios-os-x-development/ios-how-to-build-a-table-view-with-multiple-cell-types-2df91a206429 which uses a similar approach to what you have suggested (except he uses nib files and not prototype cells) and was able to replicate what the author was demonstrating. I would just like to ask. If I was to create a row that adjusts depending on the data. i.e. number of steps in a recipe. Is that still a static cell? – Chace Jun 03 '17 at 12:37