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 viewscaleAspectFit— Scales the image to fit within the view while maintaining aspect ratioscaleAspectFill— Scales the image to fill the view, cropping if necessarycenter— Centers the image in the view without scalingtop— Positions the image at the top center of the viewbottom— Positions the image at the bottom center of the viewleft— Positions the image at the left center of the viewright— Positions the image at the right center of the viewtopLeft— Positions the image at the top-left corner of the viewtopRight— Positions the image at the top-right corner of viewbottomLeft— Positions the image at the bottom-left corner of the viewbottomRight— 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
UITableViewDataSourceto provide data andUITableViewDelegatefor interaction handling - Use
dequeueReusableCellto 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.