@@ -103,6 +103,8 @@ public final class AccessibilitySnapshotView: SnapshotAndLegendView {
103103
104104 private var displayMarkers : [ DisplayMarker ] = [ ]
105105
106+ private var containerOverlays : [ UIView ] = [ ]
107+
106108 // MARK: - Public Methods
107109
108110 /// Parse the `containedView`'s accessibility and add appropriate visual elements to represent it.
@@ -117,6 +119,7 @@ public final class AccessibilitySnapshotView: SnapshotAndLegendView {
117119 $0. overlayView. removeFromSuperview ( )
118120 $0. activationPointView? . removeFromSuperview ( )
119121 }
122+ self . containerOverlays. forEach { $0. removeFromSuperview ( ) }
120123
121124 let viewController = containedView. next as? UIViewController
122125 let originalParent = viewController? . parent
@@ -153,26 +156,36 @@ public final class AccessibilitySnapshotView: SnapshotAndLegendView {
153156 containedView. layoutIfNeeded ( )
154157
155158 let parser = AccessibilityHierarchyParser ( )
159+
160+ // Render containers first if enabled (so they appear below elements in z-order)
161+ if snapshotConfiguration. overlay. showContainers {
162+ let hierarchy = parser. parseAccessibilityHierarchy (
163+ in: containedView,
164+ rotorResultLimit: snapshotConfiguration. legend. rotorResultLimit
165+ )
166+ renderContainers ( from: hierarchy)
167+ }
168+
156169 let markers = parser. parseAccessibilityElements ( in: containedView, rotorResultLimit: snapshotConfiguration. legend. rotorResultLimit)
157-
158-
170+
171+
159172 var displayMarkers : [ DisplayMarker ] = [ ]
160173 for (index, marker) in markers. enumerated ( ) {
161174 let color = snapshotConfiguration. overlay. colors [ index % snapshotConfiguration. overlay. colors. count]
162175
163176 let legendView = LegendView ( marker: marker, color: color, configuration: snapshotConfiguration. legend)
164177 addSubview ( legendView)
165-
178+
166179 let rotorResultsShapes = marker. displayRotors ( snapshotConfiguration. legend. includesCustomRotors) . flatMap ( \. resultMarkers) . compactMap ( \. shape)
167-
180+
168181 let overlayView = OverlayView (
169182 frame: snapshotView. bounds,
170183 elementShape: marker. shape,
171184 includedShapes: rotorResultsShapes,
172185 color: color)
173-
186+
174187 snapshotView. addSubview ( overlayView)
175-
188+
176189 var displayMarker = DisplayMarker (
177190 marker: marker,
178191 legendView: legendView,
@@ -209,6 +222,58 @@ public final class AccessibilitySnapshotView: SnapshotAndLegendView {
209222 self . displayMarkers = displayMarkers
210223 }
211224
225+ // MARK: - Private Methods
226+
227+ /// Renders container overlays as dashed borders
228+ private func renderContainers( from nodes: [ AccessibilityHierarchyNode ] ) {
229+ var containerIndex = 0
230+ var newOverlays : [ UIView ] = [ ]
231+
232+ func collectAndRenderContainers( from nodes: [ AccessibilityHierarchyNode ] ) {
233+ for node in nodes {
234+ switch node {
235+ case . element:
236+ break // Elements are handled separately
237+ case . container( let containerInfo, let children) :
238+ let color = snapshotConfiguration. overlay. colors [
239+ containerIndex % snapshotConfiguration. overlay. colors. count
240+ ]
241+ containerIndex += 1
242+
243+ let overlayView = createContainerOverlay ( for: containerInfo, color: color)
244+ snapshotView. addSubview ( overlayView)
245+ newOverlays. append ( overlayView)
246+
247+ // Recurse into children
248+ collectAndRenderContainers ( from: children)
249+ }
250+ }
251+ }
252+
253+ collectAndRenderContainers ( from: nodes)
254+ self . containerOverlays = newOverlays
255+ }
256+
257+ /// Creates a visual overlay for a container as a dashed border
258+ private func createContainerOverlay( for containerInfo: ContainerInfo , color: UIColor ) -> UIView {
259+ let overlayView = UIView ( )
260+ overlayView. frame = containerInfo. frame
261+ overlayView. backgroundColor = . clear
262+ overlayView. isUserInteractionEnabled = false
263+
264+ // Create dashed border layer
265+ let borderLayer = CAShapeLayer ( )
266+ borderLayer. path = UIBezierPath ( rect: overlayView. bounds) . cgPath
267+ borderLayer. fillColor = nil
268+ borderLayer. strokeColor = color. withAlphaComponent ( 0.8 ) . cgColor
269+ borderLayer. lineWidth = 4
270+ borderLayer. lineDashPattern = [ 12 , 6 ] // 12pt dash, 6pt gap
271+
272+ overlayView. layer. addSublayer ( borderLayer)
273+
274+ return overlayView
275+ }
276+
212277 // MARK: - Private Types
213278
214279 private struct DisplayMarker {
0 commit comments