frameLayout(at:) and frameLayout(with:) in StackFrameLayout: A Complete Guide

frameLayout(at:) returns the direct child FrameLayout at a specific index in constant time, while frameLayout(with:) performs a recursive search through the entire layout hierarchy to locate the FrameLayout managing a specific UIView.

FrameLayoutKit provides a DSL-based layout system for iOS that simplifies complex view hierarchies through StackFrameLayout containers. When building programmatic layouts, you often need to retrieve specific configuration objects after the initial setup, and these two methods in StackFrameLayout offer precise access to child layouts either by their positional index or by the target view they manage.

Direct Index Access with frameLayout(at:)

The frameLayout(at:) method provides immediate access to a child layout based on its position in the internal storage array. This approach is optimal when you know the exact insertion order of your views.

Implementation Details

In StackFrameLayout.swift, the implementation performs simple bounds checking before returning the element from the underlying frameLayouts array:

guard index >= 0 && index < frameLayouts.count else { return nil }
return frameLayouts[index]

This direct array lookup operates in O(1) constant time. The method returns an optional FrameLayout?, yielding nil if the supplied index falls outside the valid range. Because it accesses the internal representation directly, it respects the ignoreHiddenView flag inherited from the base FrameLayout class.

Usage Example

import FrameLayoutKit

let stack = VStackLayout {
    $0.add(UILabel())  // Index 0
    $0.add(UILabel())  // Index 1  
    $0.add(UILabel())  // Index 2
}

// Retrieve the middle layout
if let secondLayout = stack.frameLayout(at: 1) {
    secondLayout.backgroundColor = .lightGray
}

Hierarchical View Lookup with frameLayout(with:)

When you possess a reference to a UIView (perhaps from a gesture recognizer or delegate callback) and need to discover which FrameLayout controls it, use frameLayout(with:). This method traverses the entire stack hierarchy, including nested StackFrameLayout instances.

Recursive Traversal Logic

According to the source code in StackFrameLayout.swift (lines 48-68), the method executes the following steps:

  1. Self-check: If the stack's own targetView matches the search view, return self
  2. Linear search: Iterate through frameLayouts using enumeration
  3. Match detection: If a child's targetView equals the search view, return that child immediately
  4. Recursion: If a child is itself a StackFrameLayout, recursively call frameLayout(with:) on that substack
  5. Early termination: Set stop = true upon finding the first match to prevent unnecessary traversal

This algorithm runs in O(n) time complexity relative to the total number of frames in the hierarchy, plus the recursive depth for any nested stacks.

Usage Example

// Locate layout by view reference
if let firstLabel = stack.frameLayout(at: 0)?.targetView {
    if let layout = stack.frameLayout(with: firstLabel) {
        layout.backgroundColor = .yellow
    }
}

Performance Characteristics Comparison

Understanding the computational differences helps you select the appropriate method for your specific access pattern:

  • frameLayout(at:) – O(1) constant time. Use this when you know the child index and need maximum performance.
  • frameLayout(with:) – O(n) linear time. Use this when you only have a view reference and don't know its structural position.

Both methods are read-only operations that never modify the stack configuration or the underlying frameLayouts collection.

Working with Nested StackLayouts

The recursive capability of frameLayout(with:) proves essential when dealing with complex, nested hierarchies. Consider a vertical stack containing a horizontal inner stack:

let innerStack = HStackLayout {
    $0.add(UIButton())  // Button at index 0
    $0.add(UIButton())  // Button at index 1
}

let outerStack = VStackLayout {
    $0.add(UILabel())
    $0.add(innerStack)  // Nested stack added as child
}

// Find a button deep inside the nested stack
if let button = innerStack.frameLayout(at: 0)?.targetView {
    let owner = outerStack.frameLayout(with: button)
    // Recursively traverses into innerStack automatically
    print("Found button managed by:", owner!)
}

In this scenario, calling outerStack.frameLayout(with: button) automatically descends into innerStack to locate the correct FrameLayout instance, whereas outerStack.frameLayout(at: 0) would only return the immediate child at that index (the UILabel).

Summary

  • frameLayout(at:) provides O(1) direct array access to child layouts by numeric index, returning nil for out-of-bounds requests
  • frameLayout(with:) performs O(n) recursive searches through nested StackFrameLayout hierarchies to find layouts by their associated targetView
  • Both methods respect the ignoreHiddenView flag and are implemented in StackFrameLayout.swift
  • These accessors are read-only and safe to call from any thread, though layout mutations should occur on the main thread

Frequently Asked Questions

What is the time complexity difference between frameLayout(at:) and frameLayout(with:)?

frameLayout(at:) operates in O(1) constant time because it performs a single array index lookup after bounds validation. frameLayout(with:) operates in O(n) linear time where n represents the total number of frames in the hierarchy, as it must potentially examine every layout node during its recursive descent.

Can frameLayout(with:) find layouts inside nested StackFrameLayouts?

Yes. The method recursively traverses the entire layout hierarchy. When it encounters a child that is itself a StackFrameLayout, it automatically calls frameLayout(with:) on that substack until it finds a match or exhausts all possibilities.

What happens if I pass an invalid index to frameLayout(at:)?

The method returns nil. The implementation explicitly guards against negative indices or values exceeding frameLayouts.count - 1, making it safe to call with unchecked indices without risking runtime exceptions.

Do these methods respect the ignoreHiddenView setting?

Yes. Both methods operate on the internal frameLayouts collection, which already respects the ignoreHiddenView flag during layout calculations. However, note that these retrieval methods return the layout objects themselves regardless of visibility; the flag primarily affects layout computation rather than object access.

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 →