CGRect
Comparison
iOS Development
Programming
Swift

Comparing two CGRects

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

CGRect comparison appears in many UIKit tasks, including collision checks, layout verification, hit testing, and animation logic. The right comparison method depends on what you mean by match, overlap, or containment. This guide covers equality, intersection, containment, and tolerance-based comparisons with practical Swift examples.

Equality Comparison

If you need exact geometry equality, compare CGRect values directly.

swift
1import CoreGraphics
2
3let a = CGRect(x: 0, y: 0, width: 100, height: 50)
4let b = CGRect(x: 0, y: 0, width: 100, height: 50)
5
6print(a == b) // true

Exact equality is useful in deterministic layout code, but small floating-point differences can make equal-looking rectangles fail this check.

Compare with Tolerance for Floating Values

For animation and transformed coordinates, use epsilon tolerance.

swift
1import CoreGraphics
2
3func almostEqual(_ lhs: CGRect, _ rhs: CGRect, epsilon: CGFloat = 0.001) -> Bool {
4    abs(lhs.origin.x - rhs.origin.x) <= epsilon &&
5    abs(lhs.origin.y - rhs.origin.y) <= epsilon &&
6    abs(lhs.size.width - rhs.size.width) <= epsilon &&
7    abs(lhs.size.height - rhs.size.height) <= epsilon
8}
9
10let r1 = CGRect(x: 10.0001, y: 20, width: 100, height: 40)
11let r2 = CGRect(x: 10.0002, y: 20, width: 100, height: 40)
12
13print(almostEqual(r1, r2))

Tolerance checks are more stable when values come from transforms, scaling, or interpolation.

Intersection and Overlap Checks

To detect whether rectangles overlap, use intersects.

swift
1let rectA = CGRect(x: 0, y: 0, width: 100, height: 100)
2let rectB = CGRect(x: 80, y: 80, width: 40, height: 40)
3
4if rectA.intersects(rectB) {
5    print("Rectangles overlap")
6}

To compute the overlap region, use intersection.

swift
let overlap = rectA.intersection(rectB)
print(overlap) // non-null area if they overlap

This is useful for clipping, visible-area calculations, and collision response.

Containment Checks

Containment answers whether one rectangle fully includes another.

swift
1let outer = CGRect(x: 0, y: 0, width: 200, height: 200)
2let inner = CGRect(x: 40, y: 40, width: 50, height: 60)
3
4print(outer.contains(inner)) // true

You can also test whether a point lies inside a rectangle.

swift
let point = CGPoint(x: 10, y: 10)
print(outer.contains(point))

Containment checks are common in gesture handling and drag constraints.

Coordinate Space Matters

Two rectangles from different coordinate systems are not directly comparable. Convert views into a shared coordinate space before comparing.

swift
1import UIKit
2
3func frameInRoot(_ view: UIView, root: UIView) -> CGRect {
4    return view.convert(view.bounds, to: root)
5}

Always normalize coordinate space first for reliable overlap and equality logic.

Practical Layout Debug Pattern

When debugging layout regressions, print key rectangle values and compare expected against actual.

swift
func debugFrame(_ name: String, _ frame: CGRect) {
    print("\(name): x=\(frame.minX), y=\(frame.minY), w=\(frame.width), h=\(frame.height)")
}

Pair this with assertions in unit tests for deterministic, repeatable UI geometry validation.

Use Integral Rectangles for Pixel Alignment

On some UI paths, tiny fractional coordinates can cause blurry rendering. If your comparison depends on visual alignment, normalize rectangles first.

swift
let raw = CGRect(x: 10.4, y: 20.6, width: 99.7, height: 40.2)
let snapped = raw.integral
print(snapped)

Comparing normalized rectangles can reduce false mismatches in snapshot tests and layout assertions. Keep in mind that integral conversion changes geometry, so use it only for rendering-oriented checks, not physical collision logic.

Common Pitfalls

  • Using exact equality for floating-point values that should use tolerance.
  • Comparing rectangles from different coordinate spaces.
  • Confusing overlap with containment in collision logic.
  • Ignoring zero-width or zero-height rectangles that can affect intersection checks.
  • Assuming transformed view bounds match displayed frame without conversion.

Summary

  • Use direct equality only when exact matches are expected.
  • Use epsilon-based comparison for float-heavy geometry.
  • Use intersects and intersection for overlap logic.
  • Use contains for full enclosure checks.
  • Normalize coordinate spaces before any rectangle comparison.

Course illustration
Course illustration

All Rights Reserved.