vds_ios_sample/VDSSample/Protocols/CustomRotorable.swift
Matt Bruce 4820dc66cd updated samplelabel
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2023-08-26 10:50:35 -05:00

85 lines
2.6 KiB
Swift

//
// AccessibilityCustomRotorable.swift
// VDS
//
// Created by Matt Bruce on 8/24/23.
//
import Foundation
import UIKit
public protocol CustomRotorable: UIViewController {
var customRotors: [CustomRotorType] { get set }
}
extension CustomRotorable {
internal func addCustomRotor(with name: String, for trait: UIAccessibilityTraits) {
accessibilityCustomRotors = (accessibilityCustomRotors ?? []).filter { $0.name != name }
let newRotor = UIAccessibilityCustomRotor(name: name) { [weak self] predicate in
guard let self = self else { return nil }
let elements = self.view.accessibleElements(with: trait)
guard !elements.isEmpty else { return nil }
let currentIndex = elements.firstIndex(where: { ($0 as AnyObject) === predicate.currentItem.targetElement })
let count = elements.count
let nextIndex: Int
switch predicate.searchDirection {
case .next:
nextIndex = currentIndex.map { ($0 + 1) % count } ?? 0
case .previous:
nextIndex = currentIndex.map { ($0 - 1 + count) % count } ?? 0
@unknown default:
nextIndex = 0
}
guard let element = elements[nextIndex] as? NSObjectProtocol else { return nil }
return UIAccessibilityCustomRotorItemResult(targetElement: element, targetRange: nil)
}
accessibilityCustomRotors?.append(newRotor)
}
public func loadCustomRotors() {
customRotors.forEach { addCustomRotor(with: $0.name, for: $0.trait) }
}
}
public extension UIView {
func accessibleElements(with trait: UIAccessibilityTraits) -> [Any] {
var elements: [Any] = []
if isAccessibilityElement, accessibilityTraits.contains(trait) {
elements.append(self)
}
if let customAccessibilityElements = accessibilityElements {
elements.append(contentsOf: customAccessibilityElements.filter { element in
if let element = element as? UIAccessibilityElement {
return element.accessibilityTraits.contains(trait)
}
return false
})
}
subviews.forEach { elements.append(contentsOf: $0.accessibleElements(with: trait)) }
return elements
}
}
public struct CustomRotorType {
public var name: String
public var trait: UIAccessibilityTraits
public init(name: String, trait: UIAccessibilityTraits) {
self.name = name
self.trait = trait
}
}