// // UIView+Accessibility.swift // VDS // // Created by Matt Bruce on 8/4/23. // import Foundation import UIKit extension UIView { /// AccessibilityLabel helper for joining the accessibilityLabel property of all views passed in. /// - Parameters: /// - views: Array of Views that you want to join the accessibilityLabel. /// - separator: Separator used between the accessibilityLabel for each UIView. /// - Returns: Joined String. public func combineAccessibilityLabel(for views: [AnyObject], separator: String = ", ") -> String? { let labels: [String] = views.map({($0.accessibilityLabel?.isEmpty ?? true) ? nil : $0.accessibilityLabel}).compactMap({$0}) return labels.joined(separator: separator) } /// AccessibilityLabel helper for joining the accessibilityLabel property of all views passed in. /// - Parameter views: Array of Views that you want to join the accessibilityLabel. public func setAccessibilityLabel(for views: [AnyObject]) { accessibilityLabel = combineAccessibilityLabel(for: views) } /// Will tell if the view is actually visibile on screen, also it will check the hierarchy above this view. public var isVisibleOnScreen: Bool { // Ensure the view has a window, meaning it's part of the view hierarchy guard let window = self.window, !self.isHidden, self.alpha > 0 else { return false } // Check if the view's frame intersects with the window's bounds let viewFrameInWindow = self.convert(self.bounds, to: window) var isIntersecting = viewFrameInWindow.intersects(window.bounds) // Check parent views for visibility var currentView: UIView? = self while let view = currentView, isIntersecting { // If any parent has a constraint making it effectively invisible, set isIntersecting to false if view.bounds.size.width == 0 || view.bounds.size.height == 0 { isIntersecting = false break } currentView = view.superview } return isIntersecting } public func gatherAccessibilityElements(from view: AnyObject) -> [AnyObject] { var elements: [AnyObject] = [] for subview in view.subviews { if subview.isAccessibilityElement && subview.isVisibleOnScreen { elements.append(subview) } else { elements.append(contentsOf: gatherAccessibilityElements(from: subview)) } } return elements } }