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:
- Self-check: If the stack's own
targetViewmatches the search view, returnself - Linear search: Iterate through
frameLayoutsusing enumeration - Match detection: If a child's
targetViewequals the search view, return that child immediately - Recursion: If a child is itself a
StackFrameLayout, recursively callframeLayout(with:)on that substack - Early termination: Set
stop = trueupon 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, returningnilfor out-of-bounds requestsframeLayout(with:)performs O(n) recursive searches through nestedStackFrameLayouthierarchies to find layouts by their associatedtargetView- Both methods respect the
ignoreHiddenViewflag and are implemented inStackFrameLayout.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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →