Skip to main content

Building User Interfaces with UIKit

1. Creating Views

Property Description Example
frame The rectangle that defines the view's location and size in its superview's coordinate system view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
bounds The rectangle that defines the view's location and size in its own coordinate system view.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
backgroundColor The background color of the view view.backgroundColor = UIColor.red
alpha The opacity of the view, from 0.0 (transparent) to 1.0 (opaque) view.alpha = 0.5
hidden Whether the view is hidden view.isHidden = true
clipsToBounds Whether subviews are clipped to the view's bounds view.clipsToBounds = true

Example: Creating a Custom View

class CustomView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

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

    private func setupView() {
        backgroundColor = UIColor.systemBlue
        layer.cornerRadius = 8
    }
}

Example: Adding a Subview

let button = UIButton(type: .system)
button.setTitle("Tap Me", for: .normal)
button.backgroundColor = UIColor.systemGreen
button.layer.cornerRadius = 8

view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    button.widthAnchor.constraint(equalToConstant: 100),
    button.heightAnchor.constraint(equalToConstant: 40)
])

2. Working with Frames and Bounds

Property Description Value Type
frame Rectangle that defines the view's location and size in its superview’s coordinate system CGRect
bounds Rectangle that defines the view's location and size in its own coordinate system CGRect
center Center point of the view in its superview’s coordinate system CGPoint

Example: Setting Frame and Bounds

let view = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
view.backgroundColor = UIColor.red
print("Frame: " + view.frame.description)
print("Bounds: " + view.bounds.description)
Note: Modifying the frame updates both the view's position and size, while modifying bounds only affects the view’s internal coordinate system.

3. Using UILabel for Text Display

Property Value Description
text String? The text to display in the label.
font UIFont? The font used to display the text.
textColor UIColor? The color of the text.
textAlignment NSTextAlignment Alignment of the text within the label.
numberOfLines Int Maximum number of lines to display. 0 means unlimited.
lineBreakMode NSLineBreakMode How to break lines when text overflows.

Example: Basic UILabel Usage

let label = UILabel()
label.text = "Hello, World!"
label.font = UIFont.systemFont(ofSize: 17)
label.textColor = UIColor.black
label.textAlignment = .center
label.numberOfLines = 0

Example: Dynamic Text Update

class ViewController: UIViewController {
    @IBOutlet weak var statusLabel: UILabel!
    
    func updateStatus(_ message: String) {
        statusLabel.text = message
        // Optionally animate the change
        UIView.animate(withDuration: 0.3) {
            self.statusLabel.alpha = 1.0
        }
    }
}
Note: UILabel is optimized for displaying static text. For dynamic or editable text, consider using UITextField or UITextView.

4. Using UIButton for Actions

Property Values Description
setTitle(_:for:) String Sets the title of the button for a specific state
setTitleColor(_:for:) UIColor Sets the color of the title for a specific state
setBackgroundColor(_:for:) UIColor Sets the background color for a specific state
addTarget(_:action:for:) AnyObject, Selector, UIControlEvents Adds a target-action pair for a specific event type

Example: Basic Button with Action

let button = UIButton(type: .system)
button.setTitle("Tap Me", for: .normal)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

@objc func buttonTapped() {
    print("Button was tapped!")
}

Example: Button with Custom Background

let button = UIButton(type: .system)
button.setTitle("Submit", for: .normal)
button.setTitleColor(.white, for: .normal)
button.setBackgroundColor(.blue, for: .normal)
button.layer.cornerRadius = 8

extension UIButton {
    func setBackgroundColor(_ color: UIColor, for state: UIControl.State) {
        let background = CALayer()
        background.backgroundColor = color.cgColor
        background.frame = bounds
        layer.insertSublayer(background, at: 0)
    }
}

5. Working with UIImageView

Property Value Description
image UIImage? The image displayed by the UIImageView
highlightedImage UIImage? The image to display when the view is highlighted
isHighlighted Bool Indicates whether the image view is highlighted
contentMode UIView.ContentMode How the image should be resized to fit the frame
clipsToBounds Bool Whether to clip the image to the bounds of the view

Example: Setting an Image

let imageView = UIImageView()
imageView.image = UIImage(named: "sampleImage")
imageView.contentMode = .scaleAspectFit

Example: Handling Image Highlighting

let imageView = UIImageView()
imageView.image = UIImage(named: "normalImage")
imageView.highlightedImage = UIImage(named: "highlightedImage")
imageView.isHighlighted = true
Note: Ensure that image assets are added to your Xcode project or bundle for proper display.

Content Mode Options

  • scaleToFill — Scales the image to fill the view
  • scaleAspectFit — Scales the image to fit within the view while maintaining aspect ratio
  • scaleAspectFill — Scales the image to fill the view, cropping if necessary
  • center — Centers the image in the view without scaling
  • top — Positions the image at the top center of the view
  • bottom — Positions the image at the bottom center of the view
  • left — Positions the image at the left center of the view
  • right — Positions the image at the right center of the view
  • topLeft — Positions the image at the top-left corner of the view
  • topRight — Positions the image at the top-right corner of view
  • bottomLeft — Positions the image at the bottom-left corner of the view
  • bottomRight — Positions the image at the bottom-right corner of the view

6. Using UITextField for Input

Property Value Description
text String? The current text displayed in the field
placeholder String? Text shown when the field is empty
isSecureTextEntry Bool Whether to hide text (e.g., for passwords)
borderStyle UITextField.BorderStyle Visual style of the border (none, line, roundedRect)

Example: Basic UITextField Usage

let textField = UITextField()
textField.placeholder = "Enter your name"
textField.borderStyle = .roundedRect
textField.text = "John Doe"

Example: Handling Text Changes

textField.addTarget(self, action: #selector(textDidChange), for: .editingChanged)

@objc func textDidChange(_ textField: UITextField) {
    print("Text changed to: \(textField.text ?? "")")
}
Note: UITextField does not support multiline input. For that, use UITextView.

7. Using UITextView for Multiline Text

UITextView is a powerful UIKit component for displaying and editing multiline text. Unlike UILabel, it supports user interaction, text selection, and scrolling.

Property Value Description
text String The text content of the text view.
isEditable Bool Controls whether the user can edit the text.
isScrollEnabled Bool Enables or disables scrolling for content that exceeds the view’s bounds.
font UIFont The font used to display the text.
textColor UIColor The color of the displayed text.
textAlignment NSTextAlignment Aligns the text within the view (e.g., .left, .center).
backgroundColor UIColor The background color of the text view.

Example: Basic UITextView Setup

let textView = UITextView()
textView.text = "This is a multiline text view."
textView.font = UIFont.systemFont(ofSize: 16)
textView.textColor = .black
textView.backgroundColor = .white
textView.isEditable = true
textView.isScrollEnabled = true

Example: UITextView with Text Selection

let textView = UITextView()
textView.text = "Select this text to see selection behavior."
textView.isEditable = false // Prevent editing
textView.isSelectable = true // Allow selection
Note: UITextView is more resource-intensive than UILabel due to its editing capabilities. Use it only when multiline text input or selection is required.

8. Working with UIScrollView

Property Value Description
contentSize CGSize The size of the content area
contentOffset CGPoint The offset of the content area
scrollIndicatorInsets UIEdgeInsets The insets for scroll indicators
isScrollEnabled Bool Whether scrolling is enabled

Example: Basic UIScrollView Setup

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        ])
        
        let contentView = UIView()
        contentView.backgroundColor = .lightGray
        contentView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(contentView)
        
        NSLayoutConstraint.activate([
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
        ])
    }
}

Example: Adding Content to UIScrollView

import UIKit

class ContentViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        
        let contentView = UIView()
        contentView.backgroundColor = .white
        contentView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(contentView)
        
        let label = UILabel()
        label.text = "This is a long content that requires scrolling"
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            
            label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20)
        ])
    }
}

9. Using UITableView for Lists

Property Value Description
dataSource UITableViewDataSource Required protocol for providing data to the table view
delegate UITableViewDelegate Optional protocol for handling user interactions and layout
style .plain or .grouped Determines the visual appearance of the table view

Example: Basic UITableView Setup

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "Row \(indexPath.row)"
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("Selected row \(indexPath.row)")
    }
}
Note: Make sure to register a cell identifier with the table view or use a prototype cell in Interface Builder.
Method Description Return Type
numberOfRowsInSection Number of rows in a section Int
cellForRowAt Provides the cell for a specific index path UITableViewCell
didSelectRowAt Called when a row is selected Void

Example: Custom Cell with Image

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath)
    
    cell.textLabel?.text = "Item \(indexPath.row)"
    cell.imageView?.image = UIImage(named: "icon")
    
    return cell
}

Key Points

  • UITableView is used to display lists of data in a scrollable view
  • Implement UITableViewDataSource to provide data and UITableViewDelegate for interaction handling
  • Use dequeueReusableCell to efficiently reuse cells

10. Using UICollectionView for Grids

UICollectionView is a powerful component in UIKit for creating flexible, grid-based layouts. It's particularly useful for displaying content in a grid or list format with custom cell arrangements.

Example: Basic UICollectionView Setup

import UIKit

class GridViewController: UIViewController {
    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.delegate = self
        collectionView.dataSource = self
    }
}

extension GridViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GridCell", for: indexPath)
        return cell
    }
}
Property Value Description
collectionViewLayout UICollectionViewFlowLayout The layout manager used to define the grid structure.
minimumInteritemSpacing 10.0 Minimum spacing between items in the same row.
minimumLineSpacing 10.0 Minimum spacing between rows.
itemSize CGSize(width: 100, height: 100) Size of each grid item.
Note: For a true grid layout, you should configure UICollectionViewFlowLayout with appropriate itemSize, minimumInteritemSpacing, and minimumLineSpacing.

Example: Custom UICollectionViewFlowLayout

let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

collectionView.collectionViewLayout = layout

Key Features of UICollectionView Grids

  • Flexible Layouts: Supports various grid arrangements (columns, rows, staggered).
  • Custom Cells: Each cell can be customized with unique content and appearance.
  • Performance: Efficiently reuses cells to handle large datasets.

11. Working with UIStackView

Property Description Values
axis Defines the stack view's layout direction .horizontal, .vertical
distribution Defines how subviews are distributed along the axis .fill, .fillEqually, .fillProportionally, .equalSpacing, .spacing
alignment Defines how subviews are aligned perpendicular to the axis .fill, .center, .leading, .trailing, .firstBaseline, .lastBaseline
spacing Defines the spacing between subviews Double

Example: Creating a Horizontal Stack View

let stackView = UIStackView()
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.alignment = .center
stackView.spacing = 10.0

Example: Adding Subviews to a Stack View

let button1 = UIButton(type: .system)
let button2 = UIButton(type: .system)

stackView.addArrangedSubview(button1)
stackView.addArrangedSubview(button2)
Note: Subviews added with addArrangedSubview are automatically laid out by the stack view. Use addSubview instead if you want to position the subview manually.

Key Features of UIStackView

  • Automatically handles layout constraints for subviews
  • Supports both horizontal and vertical orientations
  • Provides flexible distribution and alignment options
  • Reduces boilerplate code compared to manual Auto Layout constraints

12. Understanding Responder Chain

The responder chain is a hierarchy of objects that can respond to events in iOS. When an event occurs (like a touch or keyboard input), UIKit traverses the responder chain to find an object that can handle the event.

Object Responsibility Methods
UIResponder Base class for all objects that can respond to events canResignFirstResponder, canBecomeFirstResponder
UIView Handles touch events and forwards them up the chain touchesBegan(_:with:), hitTest(_:with:)
UIViewController Manages view hierarchy and handles events for its views viewDidAppear(_:), viewWillAppear(_:)
UIApplication Root of the responder chain, handles app-level events sendEvent(_:), handleEvent(_:)

Example: Traversing the Responder Chain

class CustomView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        print("Hit test called on CustomView")
        return super.hitTest(point, with: event)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("Touches began on CustomView")
        super.touchesBegan(touches, with: event)
    }
}
Note: The responder chain is used for handling events like touches, keyboard input, and motion events. It ensures that the correct object in the view hierarchy handles these events.

Was this article helpful?