Popular Searches
Popular Course Categories
Popular Courses

Displaying Lists and Grid-Based Collections in UIKit

Displaying Lists and Grid-Based Collections in UIKit

Lists, Collections, and Dynamic Data Presentation

Displaying Lists and Grid-Based Collections in UIKit

Course: iOS App Development

Topic: Displaying Lists and Grid-Based Collections in UIKit

Course Link: iOS Training at JustAcademy

Demo Registration: Register for a Course Demo

JustAcademy Homepage: Visit JustAcademy


1. Introduction to Lists and Grid-Based Collections

Lists and grid-based collections are essential components of iOS application interfaces. They allow developers to display multiple data items in an organized, scrollable, and interactive format. Examples include contact lists, product catalogs, photo galleries, music libraries, message histories, and category screens.

UIKit provides two primary components for displaying collections of data: UITableView and UICollectionView. A table view is commonly used for vertically arranged rows, while a collection view can display items in grids, horizontal carousels, lists, and more complex layouts.

Both components support reusable cells, user interaction, scrolling, and dynamic content. Choosing the appropriate component depends on the design, structure, and interaction requirements of the application.

Learning Objectives

  • Understand the purpose of UITableView and UICollectionView.
  • Learn the role of data sources, delegates, cells, and layouts.
  • Create a vertically scrolling list using UIKit.
  • Build a grid-based collection using UICollectionView.
  • Customize cells, spacing, sections, and selection behavior.
  • Update collection content when data changes.
  • Understand reusable cells and performance optimization.
  • Apply accessibility and responsive layout practices.

2. Understanding UITableView

UITableView displays data in a single column of rows. Each row typically represents one item, such as a contact, notification, message, setting, or product summary.

A table view can present one continuous list or divide content into multiple sections. Sections can include headers and footers to help users understand how the information is organized.

Common Uses of UITableView

  • Contact lists and call histories.
  • Settings screens.
  • Chat and notification lists.
  • Transaction histories.
  • Menus and category lists.
  • Search results and task lists.

Important UITableView Components

Component Purpose
UITableView Displays and manages a scrollable list of rows.
UITableViewCell Displays the content of an individual row.
UITableViewDataSource Provides the number of rows and configures their cells.
UITableViewDelegate Handles selection and other table view interactions.
IndexPath Identifies an item by its section and row position.
UITableView.Style Controls whether the table uses a plain or grouped presentation.

3. Creating a Simple UITableView

A table view can be created in a storyboard or programmatically. The following example demonstrates a programmatic implementation using a view controller.

import UIKit

final class FruitListViewController: UIViewController,
                                     UITableViewDataSource,
                                     UITableViewDelegate {
    private let fruits = [
        "Apple",
        "Banana",
        "Orange",
        "Mango",
        "Grapes"
    ]

    private let tableView = UITableView(
        frame: .zero,
        style: .plain
    )

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "Fruit List"
        view.backgroundColor = .systemBackground

        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(
            UITableViewCell.self,
            forCellReuseIdentifier: "FruitCell"
        )

        tableView.dataSource = self
        tableView.delegate = self

        view.addSubview(tableView)

        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(
                equalTo: view.safeAreaLayoutGuide.topAnchor
            ),
            tableView.leadingAnchor.constraint(
                equalTo: view.leadingAnchor
            ),
            tableView.trailingAnchor.constraint(
                equalTo: view.trailingAnchor
            ),
            tableView.bottomAnchor.constraint(
                equalTo: view.bottomAnchor
            )
        ])
    }

    func tableView(
        _ tableView: UITableView,
        numberOfRowsInSection section: Int
    ) -> Int {
        return fruits.count
    }

    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath
    ) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(
            withIdentifier: "FruitCell",
            for: indexPath
        )

        cell.textLabel?.text = fruits[indexPath.row]
        cell.accessoryType = .disclosureIndicator

        return cell
    }

    func tableView(
        _ tableView: UITableView,
        didSelectRowAt indexPath: IndexPath
    ) {
        let selectedFruit = fruits[indexPath.row]
        print("Selected fruit: \(selectedFruit)")

        tableView.deselectRow(
            at: indexPath,
            animated: true
        )
    }
}

Explanation

  • fruits contains the data displayed by the table.
  • UITableView creates the scrolling list interface.
  • register(_:forCellReuseIdentifier:) registers the cell class for reuse.
  • numberOfRowsInSection returns the number of rows to display.
  • cellForRowAt configures each visible row.
  • didSelectRowAt responds when a user selects a row.
  • Auto Layout constraints position the table view within the screen.

In this example, the table contains one section by default. More complex applications can provide multiple sections and different cell configurations.

4. Understanding the UITableView Data Source

The data source is responsible for providing the information that a table view displays. It tells the table how many sections and rows exist and supplies the appropriate cell for each requested index path.

Common Data Source Methods

Method Purpose
numberOfSections(in:) Returns the number of sections in the table.
tableView(_:numberOfRowsInSection:) Returns the number of rows in a section.
tableView(_:cellForRowAt:) Creates or configures a reusable cell for a row.
tableView(_:titleForHeaderInSection:) Provides a section header title.
tableView(_:titleForFooterInSection:) Provides a section footer title.

Keep the data source consistent with the underlying data model. When records are inserted or deleted, update the data model and the table view together to avoid inconsistent row counts or invalid index paths.

5. Understanding UITableViewDelegate

The table view delegate manages interactions and aspects of the presentation. It can respond to row selection, configure row heights, support editing behavior, and manage other table-related events.

Example: Handling Row Selection

func tableView(
    _ tableView: UITableView,
    didSelectRowAt indexPath: IndexPath
) {
    let selectedItem = fruits[indexPath.row]

    print("You selected \(selectedItem)")

    tableView.deselectRow(
        at: indexPath,
        animated: true
    )
}

Use the selected model item to navigate to a detail screen or perform an appropriate action. Avoid relying on a hard-coded row number to identify a record because the order of the data can change.

6. Customizing UITableView Cells

Standard table view cells support common layouts, but many applications require custom cell designs containing images, subtitles, labels, badges, or action buttons. A custom UITableViewCell subclass provides more control over layout and styling.

Example Custom Cell

import UIKit

final class ProductTableViewCell: UITableViewCell {
    let productImageView = UIImageView()
    let nameLabel = UILabel()
    let priceLabel = UILabel()

    override init(
        style: UITableViewCell.CellStyle,
        reuseIdentifier: String?
    ) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        productImageView.contentMode = .scaleAspectFit
        productImageView.translatesAutoresizingMaskIntoConstraints = false

        nameLabel.font = .preferredFont(forTextStyle: .headline)
        nameLabel.adjustsFontForContentSizeCategory = true

        priceLabel.font = .preferredFont(forTextStyle: .subheadline)
        priceLabel.textColor = .secondaryLabel
        priceLabel.adjustsFontForContentSizeCategory = true

        let labelsStack = UIStackView(
            arrangedSubviews: [nameLabel, priceLabel]
        )
        labelsStack.axis = .vertical
        labelsStack.spacing = 4
        labelsStack.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(productImageView)
        contentView.addSubview(labelsStack)

        NSLayoutConstraint.activate([
            productImageView.leadingAnchor.constraint(
                equalTo: contentView.leadingAnchor,
                constant: 12
            ),
            productImageView.centerYAnchor.constraint(
                equalTo: contentView.centerYAnchor
            ),
            productImageView.widthAnchor.constraint(
                equalToConstant: 56
            ),
            productImageView.heightAnchor.constraint(
                equalToConstant: 56
            ),

            labelsStack.leadingAnchor.constraint(
                equalTo: productImageView.trailingAnchor,
                constant: 12
            ),
            labelsStack.trailingAnchor.constraint(
                equalTo: contentView.trailingAnchor,
                constant: -12
            ),
            labelsStack.centerYAnchor.constraint(
                equalTo: contentView.centerYAnchor
            ),
            labelsStack.topAnchor.constraint(
                greaterThanOrEqualTo: contentView.topAnchor,
                constant: 8
            ),
            labelsStack.bottomAnchor.constraint(
                lessThanOrEqualTo: contentView.bottomAnchor,
                constant: -8
            )
        ])
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        productImageView.image = nil
        nameLabel.text = nil
        priceLabel.text = nil
    }
}

Register the custom class using a reuse identifier and configure its properties in cellForRowAt. The prepareForReuse() method helps reset content that might otherwise remain from a previously displayed item.

7. Understanding UICollectionView

UICollectionView displays items using a configurable layout. Unlike a traditional table view, a collection view can arrange items horizontally, vertically, in grids, in carousels, or in more sophisticated compositions.

A collection view is especially useful when items include images, cards, thumbnails, or multiple visual elements. The layout object determines how items and supplementary views are positioned.

Common Uses of UICollectionView

  • Photo galleries and image grids.
  • Product catalogs and shopping categories.
  • Video thumbnails and media libraries.
  • Horizontal category selectors.
  • Dashboard cards and visual menus.
  • Calendar-style interfaces and complex content layouts.

Important UICollectionView Components

Component Purpose
UICollectionView Displays a scrollable set of items.
UICollectionViewCell Displays the visual content of an item.
UICollectionViewDataSource Provides sections, item counts, and cell content.
UICollectionViewDelegate Handles selection and interaction events.
UICollectionViewLayout Defines the arrangement of items and supplementary views.
UICollectionViewFlowLayout Provides a standard row- or column-based layout with configurable spacing.
UICollectionViewDiffableDataSource Manages collection data using stable identifiers and snapshots.

8. Creating a Grid with UICollectionView

The following example builds a basic grid of colored cards using a collection view and a flow layout. It uses programmatic Auto Layout constraints and a registered cell class.

import UIKit

final class CategoryCell: UICollectionViewCell {
    static let reuseIdentifier = "CategoryCell"

    private let titleLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)

        contentView.backgroundColor = .systemBlue
        contentView.layer.cornerRadius = 12
        contentView.layer.masksToBounds = true

        titleLabel.textAlignment = .center
        titleLabel.textColor = .white
        titleLabel.font = .preferredFont(forTextStyle: .headline)
        titleLabel.adjustsFontForContentSizeCategory = true
        titleLabel.numberOfLines = 0
        titleLabel.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(titleLabel)

        NSLayoutConstraint.activate([
            titleLabel.leadingAnchor.constraint(
                equalTo: contentView.leadingAnchor,
                constant: 6
            ),
            titleLabel.trailingAnchor.constraint(
                equalTo: contentView.trailingAnchor,
                constant: -6
            ),
            titleLabel.topAnchor.constraint(
                equalTo: contentView.topAnchor,
                constant: 6
            ),
            titleLabel.bottomAnchor.constraint(
                equalTo: contentView.bottomAnchor,
                constant: -6
            )
        ])
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    func configure(title: String) {
        titleLabel.text = title
        accessibilityLabel = title
    }
}

final class CategoryGridViewController: UIViewController,
                                        UICollectionViewDataSource,
                                        UICollectionViewDelegate {
    private let categories = [
        "Food", "Travel", "Music",
        "Books", "Sports", "Technology",
        "Fashion", "Art", "Nature"
    ]

    private let collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.minimumInteritemSpacing = 12
        layout.minimumLineSpacing = 12
        layout.sectionInset = UIEdgeInsets(
            top: 16,
            left: 16,
            bottom: 16,
            right: 16
        )

        let collection = UICollectionView(
            frame: .zero,
            collectionViewLayout: layout
        )
        collection.backgroundColor = .systemBackground
        collection.translatesAutoresizingMaskIntoConstraints = false

        return collection
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "Categories"
        view.backgroundColor = .systemBackground

        collectionView.register(
            CategoryCell.self,
            forCellWithReuseIdentifier: CategoryCell.reuseIdentifier
        )

        collectionView.dataSource = self
        collectionView.delegate = self

        view.addSubview(collectionView)

        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(
                equalTo: view.safeAreaLayoutGuide.topAnchor
            ),
            collectionView.leadingAnchor.constraint(
                equalTo: view.leadingAnchor
            ),
            collectionView.trailingAnchor.constraint(
                equalTo: view.trailingAnchor
            ),
            collectionView.bottomAnchor.constraint(
                equalTo: view.bottomAnchor
            )
        ])
    }

    func collectionView(
        _ collectionView: UICollectionView,
        numberOfItemsInSection section: Int
    ) -> Int {
        return categories.count
    }

    func collectionView(
        _ collectionView: UICollectionView,
        cellForItemAt indexPath: IndexPath
    ) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: CategoryCell.reuseIdentifier,
            for: indexPath
        ) as! CategoryCell

        cell.configure(title: categories[indexPath.item])
        return cell
    }

    func collectionView(
        _ collectionView: UICollectionView,
        didSelectItemAt indexPath: IndexPath
    ) {
        print("Selected: \(categories[indexPath.item])")
    }
}

This sample defines the cell and view controller. For a working grid, the flow layout must also provide item dimensions. Add the following delegate method inside CategoryGridViewController to calculate three columns within the available width.

extension CategoryGridViewController:
    UICollectionViewDelegateFlowLayout {

    func collectionView(
        _ collectionView: UICollectionView,
        layout collectionViewLayout: UICollectionViewLayout,
        sizeForItemAt indexPath: IndexPath
    ) -> CGSize {
        guard let layout = collectionViewLayout
            as? UICollectionViewFlowLayout else {
            return CGSize(width: 100, height: 100)
        }

        let insets = layout.sectionInset
        let spacing = layout.minimumInteritemSpacing
        let availableWidth = collectionView.bounds.width
            - insets.left
            - insets.right
            - spacing * 2

        let itemWidth = floor(availableWidth / 3)
        return CGSize(width: itemWidth, height: itemWidth)
    }
}

The sizing calculation accounts for section insets and spacing. In production, consider the device width, safe-area behavior, readable cell dimensions, and whether a different number of columns is appropriate on larger screens.

9. UICollectionView Data Source and Delegate

The collection view data source describes the content to display. It provides the number of sections, the number of items in each section, and the cell for each item.

Method Purpose
numberOfSections(in:) Returns the number of collection sections.
collectionView(_:numberOfItemsInSection:) Returns the number of items in a section.
collectionView(_:cellForItemAt:) Configures a cell for a particular item.
collectionView(_:didSelectItemAt:) Responds when an item is selected.
collectionView(_:layout:sizeForItemAt:) Provides item sizing when using the flow layout delegate.

The data source supplies content, while the layout determines where that content appears. The delegate handles interaction and can also provide layout-related information when it adopts the appropriate layout delegate protocol.

10. Understanding Collection View Layouts

A collection view layout controls the position and size of cells and supplementary views. The layout is independent of the underlying data, so the same model data can be displayed in different arrangements.

Common Layout Options

Layout Description Typical Use
UICollectionViewFlowLayout Arranges items in rows or columns using configurable spacing and sizing. Simple grids and horizontal carousels.
UICollectionViewCompositionalLayout Builds layouts from sections, groups, and items with flexible sizing. Dashboards, mixed-size cards, and complex feeds.
Custom layout subclass Provides custom positioning logic for specialized arrangements. Unique visual effects or nonstandard layouts.

Flow Layout Spacing

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 12
layout.minimumInteritemSpacing = 10
layout.sectionInset = UIEdgeInsets(
    top: 16,
    left: 16,
    bottom: 16,
    right: 16
)

minimumLineSpacing controls spacing between rows or columns depending on the scrolling direction. minimumInteritemSpacing controls spacing between items within a line. sectionInset adds padding around the content of each section.

11. Creating a Horizontal Collection View

Horizontal collection views are useful for featured products, recommended content, filters, and image carousels. With a flow layout, change the scrolling direction and provide appropriate cell dimensions.

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.itemSize = CGSize(width: 160, height: 200)
layout.minimumLineSpacing = 12
layout.sectionInset = UIEdgeInsets(
    top: 8,
    left: 16,
    bottom: 8,
    right: 16
)

let collectionView = UICollectionView(
    frame: .zero,
    collectionViewLayout: layout
)

Embed the collection view in the view hierarchy and constrain its height appropriately. The layout controls the arrangement of items, while the collection view manages scrolling and cell reuse.

12. Organizing Content into Sections

Sections divide a collection into meaningful groups. For example, a media app might display featured albums in one section and recently played tracks in another.

With traditional data sources, implement the section count and return the appropriate item count for each section. The data model must also provide a consistent mapping between each section and its items.

let groupedItems = [
    ("Popular", ["Movies", "Music", "Games"]),
    ("Learning", ["Books", "Courses", "Tutorials"])
]

func numberOfSections(
    in collectionView: UICollectionView
) -> Int {
    return groupedItems.count
}

func collectionView(
    _ collectionView: UICollectionView,
    numberOfItemsInSection section: Int
) -> Int {
    return groupedItems[section].1.count
}

For this example, the cell configuration method should use the selected section and item index to retrieve the correct string. If you use section headers, register and configure the appropriate supplementary view as well.

13. Updating Lists and Collections

When data changes, the interface should reflect the updated model. The appropriate update strategy depends on the data source design.

Reloading a Table View

items.append("New Item")
tableView.reloadData()

reloadData() reloads the table's content. It is straightforward for small changes, but targeted insertions, deletions, or updates can provide better animations and avoid unnecessary work.

Updating a Collection View

categories.append("Science")
collectionView.reloadData()

When manually managing collection view updates, ensure that the model and the collection view's displayed item counts remain synchronized. For individual updates, use the appropriate insertion, deletion, movement, or reconfiguration methods.

14. Using Diffable Data Sources

UITableViewDiffableDataSource and UICollectionViewDiffableDataSource provide a modern way to manage changing collection content. Instead of manually tracking index-based changes, a diffable data source uses stable section and item identifiers and applies snapshots of the intended state.

Benefits

  • Helps manage insertions, deletions, and moves.
  • Reduces common inconsistencies between a data model and visible cells.
  • Supports animated updates when snapshots are applied.
  • Works well for dynamic lists and collections.
  • Allows item identity to remain stable when ordering changes.

Use unique identifiers for items. If the same identifier is used for different records, the snapshot cannot reliably represent their distinct identities.

15. Cell Reuse and Performance

Table views and collection views reuse cells to reduce memory allocation and improve scrolling performance. A cell that moves offscreen may be reused to display a different item later.

Best Practices for Reusable Cells

  • Register the cell class or nib before dequeuing cells.
  • Use the correct reuse identifier.
  • Configure every visible property when a cell is prepared for an item.
  • Reset temporary state in prepareForReuse() when necessary.
  • Avoid creating expensive resources repeatedly during cell configuration.
  • Load remote images asynchronously and ensure reused cells display the correct image.
  • Use prefetching where data or image preparation is expensive.
  • Keep layout constraints efficient and avoid unnecessary repeated calculations.

Why Cell Reuse Matters

Imagine a collection with 500 photos. Creating a new view for every photo at once would consume unnecessary resources. Cell reuse lets the collection view maintain a smaller number of reusable cells for the visible area and nearby content.

16. Selection, Editing, and User Interaction

Lists and grids can respond to user selection, allow deletion, support reordering, and present additional actions. Use delegate methods or modern configuration APIs to implement these interactions.

Table View Selection

Implement tableView(_:didSelectRowAt:) to respond when a user taps a row. Use the selected model identifier or object to open the appropriate detail view.

Collection View Selection

Implement collectionView(_:didSelectItemAt:) to respond when a user taps a grid item. A selected photo might open a full-screen viewer, while a selected category might navigate to a filtered product screen.

Deleting Rows

func tableView(
    _ tableView: UITableView,
    commit editingStyle: UITableViewCell.EditingStyle,
    forRowAt indexPath: IndexPath
) {
    guard editingStyle == .delete else { return }

    items.remove(at: indexPath.row)
    tableView.deleteRows(
        at: [indexPath],
        with: .automatic
    )
}

This example assumes items is a mutable array that is the table's data source. In a real app, update the persistent model or repository as well as the displayed collection.

17. Accessibility for Lists and Grids

Accessible lists and grids should communicate meaningful content and actions to users of assistive technologies. UIKit controls offer built-in accessibility behavior, but custom cells may require additional configuration.

  • Use clear, descriptive labels for images and interactive elements.
  • Prefer semantic text styles and support Dynamic Type.
  • Maintain sufficient contrast between text and backgrounds.
  • Make touch targets comfortable to use.
  • Ensure selection and action states are understandable.
  • Do not rely on color alone to communicate status.
  • Test navigation with VoiceOver and larger accessibility text sizes.
  • Verify that custom cells expose their important content in a logical order.

18. Responsive Layout and Device Adaptation

Lists and grids should adapt to different screen sizes, orientations, and accessibility settings. A grid that looks good on a narrow phone may need more columns on a larger device.

Responsive Design Recommendations

  • Use Auto Layout to position the table or collection view.
  • Calculate grid item sizes from the available width rather than hard-coding a single device-specific width.
  • Account for section insets and inter-item spacing.
  • Use self-sizing cells when content height varies significantly.
  • Test portrait and landscape orientations when supported.
  • Allow text to grow and wrap instead of clipping longer labels.
  • Consider compositional layouts for screens that combine multiple content styles.

19. UITableView vs. UICollectionView

Feature UITableView UICollectionView
Default presentation Rows in a single column. Flexible item arrangement.
Best suited for Text-focused lists and sequential records. Grids, galleries, cards, and complex layouts.
Layout control Primarily row and section presentation. Flow, compositional, or custom layouts.
Reusable cells Supported through UITableViewCell. Supported through UICollectionViewCell.
Sections Supported. Supported.
Horizontal scrolling Not the typical table view presentation. Supported through appropriate layouts.
Modern diffable data source UITableViewDiffableDataSource. UICollectionViewDiffableDataSource.

Choose UITableView for straightforward row-based content. Choose UICollectionView when the visual arrangement needs more flexibility or when the same screen contains varied item layouts.

20. Common Errors and Troubleshooting

Problem Possible Cause Solution
Cells appear blank. The cell configuration method does not assign content or uses the wrong data index. Check the data source and cell configuration code.
App crashes while dequeuing a cell. The cell class or nib was not registered, or the reuse identifier is incorrect. Register the cell and use the matching identifier.
Incorrect item count. The data source and model have different counts. Update the data model and UI consistently.
Wrong content appears during scrolling. A reused cell retains state from a previous item. Configure all relevant properties and reset reusable state.
Grid cells are too wide or too narrow. Item sizing ignores available width, insets, or spacing. Calculate the dimensions based on the collection view's bounds.
Selection opens the wrong record. Code relies on fixed indexes instead of current model data. Map the selected index path to the current data model.
Scrolling is slow. Cell configuration performs expensive work or synchronously loads images. Optimize configuration, reuse resources, and consider prefetching.
Content is inaccessible. Custom controls lack meaningful accessibility information. Add descriptive labels and test with VoiceOver.

21. Practical Project: Product Catalog

Create a product catalog screen that displays the same product data in a list and a grid. This project demonstrates how the same model can support different UIKit presentations.

Project Requirements

  • Create a product model with an identifier, name, price, and optional image.
  • Build a table view that displays product names and prices.
  • Build a collection view that displays product cards in a grid.
  • Support selecting a product to open a detail screen.
  • Add sorting by name or price.
  • Update the list or grid when products are added or removed.
  • Use reusable cells and appropriate Auto Layout constraints.
  • Test the screen on different device sizes and accessibility settings.

Sample Product Model

import Foundation

struct Product: Identifiable {
    let id: UUID
    let name: String
    let price: Decimal
    let imageName: String?

    init(
        id: UUID = UUID(),
        name: String,
        price: Decimal,
        imageName: String? = nil
    ) {
        self.id = id
        self.name = name
        self.price = price
        self.imageName = imageName
    }
}

Use this model as the shared source of truth for both views. The table view can present each product as a row, while the collection view can display the same product as a card with an image and price.

Suggested Implementation Steps

  1. Create the product model and a sample array of products.
  2. Implement a table view controller and configure its data source.
  3. Create a custom product table cell.
  4. Implement a collection view with a flow layout.
  5. Create a product card cell and calculate responsive item sizes.
  6. Connect selection events to a product detail screen.
  7. Add sorting and test the results in both presentations.
  8. Test empty states, long product names, and scrolling performance.

22. Practice Exercises

  1. Create a contact list using UITableView with names and phone numbers.
  2. Build a photo gallery using UICollectionView with three columns.
  3. Add section headers to a list grouped by category.
  4. Implement row selection to open a detail view controller.
  5. Create a horizontal collection view for featured products.
  6. Implement deletion in a table view and keep the model synchronized.
  7. Use a diffable data source to update a collection with stable identifiers.
  8. Improve a custom cell to support Dynamic Type and VoiceOver.

23. Interview Questions and Answers

Q1. What is UITableView?

Answer: UITableView is a UIKit component that displays data as a vertically scrolling collection of rows arranged in one column.

Q2. What is UICollectionView?

Answer: UICollectionView displays items using a configurable layout, supporting grids, horizontal lists, carousels, and complex arrangements.

Q3. What is the role of a data source?

Answer: The data source provides the number of sections and items and configures the cells used to present the data.

Q4. What is the difference between a data source and a delegate?

Answer: A data source supplies the content, while a delegate handles interactions and certain presentation-related events.

Q5. Why are reusable cells important?

Answer: Cell reuse reduces unnecessary view creation, lowers memory usage, and helps scrolling remain smooth.

Q6. What is IndexPath?

Answer: An index path identifies an item's position by its section and row or item index.

Q7. What is UICollectionViewFlowLayout?

Answer: It arranges collection view items in rows or columns with configurable dimensions, spacing, and section insets.

Q8. What is a diffable data source?

Answer: It manages collection content using stable identifiers and snapshots, simplifying dynamic updates and animated changes.

Q9. How do you handle item selection?

Answer: Use tableView(_:didSelectRowAt:) for table rows or collectionView(_:didSelectItemAt:) for collection items.

Q10. How can you improve scrolling performance?

Answer: Reuse cells correctly, avoid expensive synchronous work in cell configuration, prepare images efficiently, and consider data prefetching for expensive content.

Q11. When should you use UICollectionView instead of UITableView?

Answer: Use a collection view when you need a grid, horizontal carousel, flexible layout, or multiple types of content arrangements.

Q12. How do you make collection layouts responsive?

Answer: Calculate item sizes using the available width, section insets, and spacing, and test the layout across device sizes and orientations.

24. Quick Revision Checklist

  • UITableView: Displays row-based lists.
  • UICollectionView: Displays items using flexible layouts.
  • UITableViewCell: Represents a table row.
  • UICollectionViewCell: Represents a collection item.
  • Data source: Provides data and configures cells.
  • Delegate: Handles interactions and related events.
  • Flow layout: Arranges collection items in rows or columns.
  • Compositional layout: Supports flexible, section-based arrangements.
  • Cell reuse: Improves resource efficiency and scrolling performance.
  • Diffable data source: Simplifies dynamic collection updates.
  • Accessibility: Makes list and grid content usable by more people.
  • Responsive sizing: Helps layouts adapt to available screen space.

25. Conclusion

Displaying lists and grid-based collections is a fundamental UIKit skill. UITableView is effective for conventional row-based content, while UICollectionView provides greater flexibility for grids, galleries, carousels, and complex layouts.

By understanding data sources, delegates, reusable cells, layout configuration, dynamic updates, and accessibility, developers can build efficient and user-friendly interfaces. Practice with the Product Catalog project to gain experience presenting the same data in different layouts and responding to user interactions.

Explore the iOS course: iOS App Development Training at JustAcademy

Register for a demo: JustAcademy Demo Registration

Visit the homepage: JustAcademy

Previous Next
whatsapp