diff --git a/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+EffectiveProperties.swift b/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+EffectiveProperties.swift new file mode 100644 index 00000000..b585fdbb --- /dev/null +++ b/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+EffectiveProperties.swift @@ -0,0 +1,81 @@ +// +// Copyright 2024 Block Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +extension NSObject { + + var effectiveAccessibilityLabel: String? { + #if swift(>=5.9) + if #available(iOS 17.0, *) { + return accessibilityLabelBlock?() ?? accessibilityLabel + } else { + return accessibilityLabel + } + #else + return accessibilityLabel + #endif + } + + var effectiveAccessibilityValue: String? { + #if swift(>=5.9) + if #available(iOS 17.0, *) { + return accessibilityValueBlock?() ?? accessibilityValue + } else { + return accessibilityValue + } + #else + return accessibilityValue + #endif + } + + var effectiveAccessibilityHint: String? { + #if swift(>=5.9) + if #available(iOS 17.0, *) { + return accessibilityHintBlock?() ?? accessibilityHint + } else { + return accessibilityHint + } + #else + return accessibilityHint + #endif + } + + var effectiveAccessibilityTraits: UIAccessibilityTraits? { + #if swift(>=5.9) + if #available(iOS 17.0, *) { + return accessibilityTraitsBlock?() ?? accessibilityTraits + } else { + return accessibilityTraits + } + #else + return accessibilityTraits + #endif + } + + var effectiveAccessibilityLanguage: String? { + #if swift(>=5.9) + if #available(iOS 17.0, *) { + return accessibilityLanguageBlock?() ?? accessibilityLanguage + } else { + return accessibilityLanguage + } + #else + return accessibilityLanguage + #endif + } + +} diff --git a/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift b/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift index ad0fa500..295f9760 100644 --- a/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift +++ b/Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift @@ -20,9 +20,9 @@ extension NSObject { /// Returns a tuple consisting of the `description` and (optionally) a `hint` that VoiceOver will read for the object. func accessibilityDescription(context: AccessibilityHierarchyParser.Context?) -> (description: String, hint: String?) { - var accessibilityDescription = accessibilityLabelOverride(for: context) ?? accessibilityLabel ?? "" + var accessibilityDescription = accessibilityLabelOverride(for: context) ?? effectiveAccessibilityLabel ?? "" - var hintDescription = accessibilityHint?.nonEmpty() + var hintDescription = effectiveAccessibilityHint?.nonEmpty() let strings = Strings(locale: accessibilityLanguage) @@ -36,7 +36,7 @@ extension NSObject { switch context { case let .dataTableCell(row: row, column: column, width: width, height: height, isFirstInRow: isFirstInRow, rowHeaders: rowHeaders, columnHeaders: columnHeaders): let headersDescription = (rowHeaders + columnHeaders).map { header -> String in - switch (header.accessibilityLabel?.nonEmpty(), header.accessibilityValue?.nonEmpty()) { + switch (header.effectiveAccessibilityLabel?.nonEmpty(), header.effectiveAccessibilityValue?.nonEmpty()) { case (nil, nil): return "" case let (.some(label), nil): @@ -74,7 +74,7 @@ extension NSObject { descriptionContainsContext = false } - if let accessibilityValue = accessibilityValue?.nonEmpty(), !hidesAccessibilityValue(for: context) { + if let accessibilityValue = effectiveAccessibilityValue?.nonEmpty(), !hidesAccessibilityValue(for: context) { if let existingDescription = accessibilityDescription.nonEmpty() { if descriptionContainsContext { accessibilityDescription += " \(accessibilityValue)" @@ -114,7 +114,7 @@ extension NSObject { traitSpecifiers.append(strings.switchButtonTraitName) } - switch accessibilityValue { + switch effectiveAccessibilityValue { case "1": traitSpecifiers.append(strings.switchButtonOnStateName) case "0": @@ -229,7 +229,7 @@ extension NSObject { } } - let hasHintOnly = (accessibilityHint?.nonEmpty() != nil) && (accessibilityLabel?.nonEmpty() == nil) && (accessibilityValue?.nonEmpty() == nil) + let hasHintOnly = (effectiveAccessibilityHint?.nonEmpty() != nil) && (effectiveAccessibilityLabel?.nonEmpty() == nil) && (effectiveAccessibilityValue?.nonEmpty() == nil) let hidesAdjustableHint = accessibilityTraits.contains(.notEnabled) || accessibilityTraits.contains(.switchButton) || hasHintOnly if accessibilityTraits.contains(.adjustable) && !hidesAdjustableHint { if let existingHintDescription = hintDescription?.nonEmpty()?.strippingTrailingPeriod() { @@ -276,8 +276,6 @@ extension NSObject { } } - // MARK: - Private Static Properties - // MARK: - Private private struct Strings {