How FrameLayout's sizeThatFits Calculates Intrinsic Content Size in iOS

FrameLayout's sizeThatFits method calculates intrinsic content size through an 11-step pipeline that validates visibility, subtracts edge insets, queries the target view's natural dimensions, applies ratio constraints, and clamps results to min/max bounds before re-adding insets.

FrameLayoutKit provides a declarative layout system for iOS that simplifies view sizing through programmable constraints. The sizeThatFits(_:ignoreHiddenView:) method in FrameLayout.swift serves as the core algorithm for determining how much space a layout requires. This analysis examines the precise calculation flow as implemented in the kennic/framelayoutkit repository.

Step-by-Step Algorithm Pipeline

The calculation follows a strict sequence defined at [L70-L102] of FrameLayout.swift, beginning with early validation and ending with bounds clamping.

1. Early Exit Conditions

The method first checks disabled states, returning CGSize.zero immediately at [L70-L71]. It executes the willSizeThatFitsBlock hook and, when ignoreHiddenView is true, returns .zero if the layout or its targetView is hidden at [L72-L74].

2. Fixed Size Optimization

If minSize equals maxSize and both dimensions exceed zero, the fixed size returns instantly at [L75-L76], bypassing expensive measurement operations.

3. Edge Inset Removal

The incoming size constraint reduces by the layout's edgeInsets (horizontal and vertical components) at [L78-L81]. This calculation creates the available content area by subtracting padding from the proposed bounds.

4. Content Size Computation

The method calls contentSizeThatFits(size:) at [L87-L89] with the inset-free dimensions to obtain the raw size the targetView requires.

5. Height Ratio Application

When heightRatio > 0, the width derives from the content size (or forced intrinsic width) and the height calculates as width * heightRatio at [L82-L86]. This maintains aspect ratio constraints during sizing.

6. Intrinsic Size Flags

If isIntrinsicSizeEnabled is false, the width forces to the supplied container width; otherwise, the width from step 5 persists at [L89-L92].

7. Constraint Application and Finalization

The result clamps to the layout's minSize and maxSize at [L94]. If non-zero, the original edge insets re-add at [L96-L97]. The final size never exceeds the original constraint size at [L99-L100], with the calculated CGSize returning at [L101-L102].

The contentSizeThatFits Helper Method

The contentSizeThatFits(size:) helper at [L24-L57] queries the targetView for its own sizeThatFits(_:) implementation. If minContentSize == maxContentSize, it returns a fixed content size immediately. When shouldCacheSize is enabled, results store in sizeCacheData using a key composed of the view's memory address and queried size. The method adds any extendSize and enforces minContentSize/maxContentSize constraints independently of the layout-level boundaries.

intrinsicContentSize Implementation

The layout's intrinsicContentSize property at [L74-L85] calls contentSizeThatFits using the device screen width (or visible window width on VisionOS) with an infinite height. This provides the intrinsic content size to Auto Layout systems, ensuring the layout reports its natural dimensions during constraint resolution.

Practical Implementation Example

import UIKit
import FrameLayoutKit

let label = UILabel()
label.text = "Hello, FrameLayout!"
label.numberOfLines = 0

let layout = FrameLayout()
layout.targetView = label
layout.edgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
layout.minSize = CGSize(width: 100, height: 0)

let containerWidth: CGFloat = 200
let fitSize = layout.sizeThatFits(CGSize(width: containerWidth,
                                        height: .greatestFiniteMagnitude))

print("Layout wants size: \(fitSize)")

This example demonstrates the inset subtraction (removing 16 points total), target view querying, and minimum width enforcement workflow.

Summary

  • FrameLayout.swift contains the core sizing algorithm at lines 70-102.
  • The method validates enabled/visible states before processing calculations.
  • Edge insets subtract from incoming constraints and re-add to final results.
  • Height ratios and intrinsic size flags modify dimensions before clamping.
  • Min/max size constraints enforce layout boundaries at two distinct stages.
  • Caching via sizeCacheData optimizes repeated size calculations when enabled.

Frequently Asked Questions

How does FrameLayout handle hidden views during size calculation?

When ignoreHiddenView is true, sizeThatFits returns CGSize.zero immediately if the layout or its targetView is hidden, as implemented at [L72-L74] in FrameLayout.swift. This prevents hidden views from contributing to layout calculations while respecting the willSizeThatFitsBlock hook.

What is the difference between minSize/maxSize and minContentSize/maxContentSize?

The minSize and maxSize constraints apply to the final layout dimensions including edge insets at [L94], while minContentSize and maxContentSize constrain the raw content inside contentSizeThatFits at [L24-L57]. This architectural separation allows distinct control over the layout container versus its internal content boundaries.

Does FrameLayout cache size calculations?

Yes, when shouldCacheSize is enabled, contentSizeThatFits stores results in sizeCacheData using a key composed of the view's memory address and queried size at [L24-L57]. This optimization prevents redundant sizeThatFits calls on the target view during repeated layout passes, improving performance in complex view hierarchies.

How does the heightRatio parameter affect intrinsic sizing?

When heightRatio exceeds zero, the method calculates height as width * heightRatio at [L82-L86], overriding the natural height from the target view. This maintains aspect ratio constraints during the sizing calculation before the system applies min/max limits, ensuring proportional dimensions regardless of content changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →