diff --git a/VDS/BaseClasses/Control.swift b/VDS/BaseClasses/Control.swift index 434a1a88..aa7443a2 100644 --- a/VDS/BaseClasses/Control.swift +++ b/VDS/BaseClasses/Control.swift @@ -46,15 +46,11 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable { // MARK: - Public Properties //-------------------------------------------------- open var shouldUpdateView: Bool = true - - open var shouldUpdateAccessibility: Bool = true - + open var userInfo = [String: Primitive]() open var surface: Surface = .light { didSet { setNeedsUpdate() } } - open var accessibilityAction: ((Control) -> Void)? - /// Whether the Control is selected or not. open override var isSelected: Bool { didSet { setNeedsUpdate() } } @@ -123,22 +119,138 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable { //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- - /// Implement accessibilityActivate on an element in order to handle the default action. - /// - Returns: Based on whether the userInteraction is enabled. - open override func accessibilityActivate() -> Bool { - // Hold state in case User wanted isAnimated to remain off. - guard isEnabled, isUserInteractionEnabled else { return false } - - if let accessibilityAction { - accessibilityAction(self) - } - - sendActions(for: .touchUpInside) - return true - } - open override func layoutSubviews() { super.layoutSubviews() setNeedsUpdate() } + + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var shouldUpdateAccessibility: Bool = true + + open var accessibilityAction: ((Control) -> Void)? + + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } + + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + + open override func accessibilityActivate() -> Bool { + guard isEnabled, isUserInteractionEnabled else { return false } + var value = true + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// } else if let block = accessibilityActivateBlock { +// value = block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// value = block() +// } +// +// } else { + if let block = accessibilityAction { + block(self) + + } else if let block = bridge_accessibilityActivateBlock { + value = block() + } +// } + + sendActions(for: .touchUpInside) + return value + + } + } diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 35999cf6..d1683aa3 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -137,13 +137,33 @@ open class SelectorBase: Control, SelectorControlable { open override func accessibilityActivate() -> Bool { guard isEnabled, isUserInteractionEnabled else { return false } - - if let accessibilityAction { - accessibilityAction(self) - } else { - toggle() - } - - return true + guard isEnabled, isUserInteractionEnabled else { return false } + var value = true + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// +// } else if let block = accessibilityActivateBlock { +// value = block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// value = block() +// +// } else { +// toggle() +// } +// } else { + if let block = accessibilityAction { + block(self) + + } else if let block = bridge_accessibilityActivateBlock { + value = block() + + } else { + toggle() + } +// } + return value } } diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index 63159d93..0326ac52 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -147,7 +147,7 @@ open class SelectorItemBase: Control, Errorable, Changea open var accessibilityValueText: String? - open override var accessibilityAction: ((Control) -> Void)? { + open override var accessibilityAction: ((Control) -> Void)? { didSet { selectorView.accessibilityAction = { [weak self] selectorItemBase in guard let self else { return } @@ -377,13 +377,32 @@ open class SelectorItemBase: Control, Errorable, Changea open override func accessibilityActivate() -> Bool { guard isEnabled, isUserInteractionEnabled else { return false } - - if let accessibilityAction { - accessibilityAction(self) - } else { - toggle() - } - - return true + var value = true + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// +// } else if let block = accessibilityActivateBlock { +// value = block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// value = block() +// +// } else { +// toggle() +// } +// } else { + if let block = accessibilityAction { + block(self) + + } else if let block = bridge_accessibilityActivateBlock { + value = block() + + } else { + toggle() + } +// } + return value } } diff --git a/VDS/BaseClasses/View.swift b/VDS/BaseClasses/View.swift index ec3f8dd0..288a8cdc 100644 --- a/VDS/BaseClasses/View.swift +++ b/VDS/BaseClasses/View.swift @@ -46,17 +46,13 @@ open class View: UIView, ViewProtocol, UserInfoable { //-------------------------------------------------- open var shouldUpdateView: Bool = true - open var shouldUpdateAccessibility: Bool = true - /// Dictionary for keeping information for this Control use only Primitives. open var userInfo = [String: Primitive]() open var surface: Surface = .light { didSet { setNeedsUpdate() } } open var isEnabled: Bool = true { didSet { setNeedsUpdate() } } - - open var accessibilityAction: ((View) -> Void)? - + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -89,18 +85,144 @@ open class View: UIView, ViewProtocol, UserInfoable { surface = .light isEnabled = true } - - open override func accessibilityActivate() -> Bool { - guard isEnabled, isUserInteractionEnabled else { return false } - if let accessibilityAction { - accessibilityAction(self) - } - return true - } - + open override func layoutSubviews() { super.layoutSubviews() setNeedsUpdate() } + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var shouldUpdateAccessibility: Bool = true + + open var accessibilityAction: ((View) -> Void)? + + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } +// + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + + open override func accessibilityActivate() -> Bool { + guard isEnabled, isUserInteractionEnabled else { return false } + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// return true +// } else if let block = accessibilityActivateBlock { +// return block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// return block() +// +// } else { +// return true +// +// } +// +// } else { + if let block = accessibilityAction { + block(self) + return true + + } else if let block = bridge_accessibilityActivateBlock { + return block() + + } else { + return true + + } +// } + } + } diff --git a/VDS/Classes/AccessibilityActionElement.swift b/VDS/Classes/AccessibilityActionElement.swift index df3b6ed9..cc3487f9 100644 --- a/VDS/Classes/AccessibilityActionElement.swift +++ b/VDS/Classes/AccessibilityActionElement.swift @@ -10,10 +10,10 @@ import UIKit /// Custom UIAccessibilityElement that allows you to set the default action used in accessibilityActivate. public class AccessibilityActionElement: UIAccessibilityElement { - var action: (() -> Void)? + public var accessibilityAction: AXVoidReturnBlock? public override func accessibilityActivate() -> Bool { - action?() + accessibilityAction?() return true } } diff --git a/VDS/Components/Buttons/ButtonBase.swift b/VDS/Components/Buttons/ButtonBase.swift index 56a23011..e5a80e2e 100644 --- a/VDS/Components/Buttons/ButtonBase.swift +++ b/VDS/Components/Buttons/ButtonBase.swift @@ -50,8 +50,6 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { //-------------------------------------------------- /// Key of whether or not updateView() is called in setNeedsUpdate() open var shouldUpdateView: Bool = true - - open var shouldUpdateAccessibility: Bool = true open var surface: Surface = .light { didSet { setNeedsUpdate() } } @@ -77,8 +75,6 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { /// Whether the Button should handle the isHighlighted state. open var shouldHighlight: Bool { isHighlighting == false } - - open var accessibilityAction: ((ButtonBase) -> Void)? /// Whether the Control is highlighted or not. open override var isHighlighted: Bool { @@ -143,16 +139,7 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { shouldUpdateView = true setNeedsUpdate() } - - open override func accessibilityActivate() -> Bool { - guard isEnabled, isUserInteractionEnabled else { return false } - if let accessibilityAction { - accessibilityAction(self) - } - sendActions(for: .touchUpInside) - return true - } - + //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- @@ -185,6 +172,135 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { } } + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var shouldUpdateAccessibility: Bool = true + + open var accessibilityAction: ((ButtonBase) -> Void)? + + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } + + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + + open override func accessibilityActivate() -> Bool { + guard isEnabled, isUserInteractionEnabled else { return false } + var value = true + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// } else if let block = accessibilityActivateBlock { +// value = block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// value = block() +// } +// +// } else { + if let block = accessibilityAction { + block(self) + + } else if let block = bridge_accessibilityActivateBlock { + value = block() + } +// } + + sendActions(for: .touchUpInside) + return value + + } + } // MARK: AppleGuidelinesTouchable diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index c5b760a7..b0a85e7e 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -108,8 +108,6 @@ open class Label: UILabel, ViewProtocol, UserInfoable { /// Key of whether or not updateView() is called in setNeedsUpdate() open var shouldUpdateView: Bool = true - open var shouldUpdateAccessibility: Bool = true - /// Will determine if a scaled font should be used for the font. open var useScaledFont: Bool = false { didSet { setNeedsUpdate() }} @@ -132,8 +130,6 @@ open class Label: UILabel, ViewProtocol, UserInfoable { /// Line break mode for the label, default is set to word wrapping. open override var lineBreakMode: NSLineBreakMode { didSet { setNeedsUpdate() }} - open var accessibilityAction: ((Label) -> Void)? - /// Text that will be used in the label. private var _text: String! override open var text: String! { @@ -366,7 +362,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { let labelAction = LabelAction(range: actionable.range, action: actionable.action) // set the action of the accessibilityElement - customAccessibilityAction?.action = { [weak self] in + customAccessibilityAction?.accessibilityAction = { [weak self] in guard let self, isEnabled else { return } labelAction.performAction() } @@ -456,10 +452,139 @@ open class Label: UILabel, ViewProtocol, UserInfoable { return element } + + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var shouldUpdateAccessibility: Bool = true + + open var accessibilityAction: ((Label) -> Void)? + + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } + + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + open override func accessibilityActivate() -> Bool { - guard let accessibilityAction, isEnabled, isUserInteractionEnabled else { return false } - accessibilityAction(self) - return true + guard isEnabled, isUserInteractionEnabled else { return false } + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// return true +// } else if let block = accessibilityActivateBlock { +// return block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// return block() +// +// } else { +// return true +// +// } +// +// } else { + if let block = accessibilityAction { + block(self) + return true + + } else if let block = bridge_accessibilityActivateBlock { + return block() + + } else { + return true + + } +// } } } diff --git a/VDS/Components/TextFields/InputField/TextField.swift b/VDS/Components/TextFields/InputField/TextField.swift index 800d836b..81e749b2 100644 --- a/VDS/Components/TextFields/InputField/TextField.swift +++ b/VDS/Components/TextFields/InputField/TextField.swift @@ -47,7 +47,10 @@ open class TextField: UITextField, ViewProtocol, Errorable { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - private var formatLabel = Label().with { + /// Key of whether or not updateView() is called in setNeedsUpdate() + open var shouldUpdateView: Bool = true + + private var formatLabel = Label().with { $0.tag = 999 $0.textColorConfiguration = ViewColorConfiguration().with { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) @@ -63,9 +66,6 @@ open class TextField: UITextField, ViewProtocol, Errorable { /// Will determine if a scaled font should be used for the titleLabel font. open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } } - - /// Key of whether or not updateView() is called in setNeedsUpdate() - open var shouldUpdateView: Bool = true open var shouldUpdateAccessibility: Bool = true @@ -76,8 +76,6 @@ open class TextField: UITextField, ViewProtocol, Errorable { open var errorText: String? { didSet { setNeedsUpdate() } } open var lineBreakMode: NSLineBreakMode = .byClipping { didSet { setNeedsUpdate() } } - - open var accessibilityAction: ((TextField) -> Void)? open override var isEnabled: Bool { didSet { setNeedsUpdate() } } @@ -213,17 +211,6 @@ open class TextField: UITextField, ViewProtocol, Errorable { return success } - open override func accessibilityActivate() -> Bool { - guard isEnabled, isUserInteractionEnabled else { return false } - - if let accessibilityAction { - accessibilityAction(self) - return true - } else { - return super.accessibilityActivate() - } - } - //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- @@ -244,7 +231,139 @@ open class TextField: UITextField, ViewProtocol, Errorable { attributedText = nil } } + + + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var accessibilityAction: ((TextField) -> Void)? + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } + + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + + open override func accessibilityActivate() -> Bool { + guard isEnabled, isUserInteractionEnabled else { return false } + +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// return true +// } else if let block = accessibilityActivateBlock { +// return block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// return block() +// +// } else { +// return super.accessibilityActivate() +// +// } +// +// } else { + if let block = accessibilityAction { + block(self) + return true + + } else if let block = bridge_accessibilityActivateBlock { + return block() + + } else { + return super.accessibilityActivate() + + } +// } + } } extension UITextField { diff --git a/VDS/Components/TextFields/TextArea/TextView.swift b/VDS/Components/TextFields/TextArea/TextView.swift index 3832d2e5..bbb7b329 100644 --- a/VDS/Components/TextFields/TextArea/TextView.swift +++ b/VDS/Components/TextFields/TextArea/TextView.swift @@ -48,8 +48,6 @@ open class TextView: UITextView, ViewProtocol, Errorable { /// Key of whether or not updateView() is called in setNeedsUpdate() open var shouldUpdateView: Bool = true - open var shouldUpdateAccessibility: Bool = true - open var surface: Surface = .light { didSet { setNeedsUpdate() } } /// Array of LabelAttributeModel objects used in rendering the text. @@ -68,8 +66,6 @@ open class TextView: UITextView, ViewProtocol, Errorable { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} - open var accessibilityAction: ((TextView) -> Void)? - open var showError: Bool = false { didSet { setNeedsUpdate() } } open var errorText: String? { didSet { setNeedsUpdate() } } @@ -149,15 +145,139 @@ open class TextView: UITextView, ViewProtocol, Errorable { setNeedsUpdate() } + + //-------------------------------------------------- + // MARK: - Accessibility + //-------------------------------------------------- + open var shouldUpdateAccessibility: Bool = true + + open var accessibilityAction: ((TextView) -> Void)? + + private var _isAccessibilityElement: Bool = false + open override var isAccessibilityElement: Bool { + get { + var block: AXBoolReturnBlock? + +// if #available(iOS 17, *) { +// block = isAccessibilityElementBlock +// } + + if block == nil { + block = bridge_isAccessibilityElementBlock + } + + if let block { + return block() + } else { + return _isAccessibilityElement + } + } + set { + _isAccessibilityElement = newValue + } + } + + private var _accessibilityLabel: String? + open override var accessibilityLabel: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityLabelBlock +// } + + if block == nil { + block = bridge_accessibilityLabelBlock + } + + if let block { + return block() + } else { + return _accessibilityLabel + } + } + set { + _accessibilityLabel = newValue + } + } + + private var _accessibilityHint: String? + open override var accessibilityHint: String? { + get { + var block: AXStringReturnBlock? +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityHintBlock + } + + if let block { + return block() + } else { + return _accessibilityHint + } + } + set { + _accessibilityHint = newValue + } + } + + private var _accessibilityValue: String? + open override var accessibilityValue: String? { + get { + var block: AXStringReturnBlock? + +// if #available(iOS 17, *) { +// block = accessibilityHintBlock +// } + + if block == nil { + block = bridge_accessibilityValueBlock + } + + if let block{ + return block() + } else { + return _accessibilityValue + } + } + set { + _accessibilityValue = newValue + } + } + open override func accessibilityActivate() -> Bool { guard isEnabled, isUserInteractionEnabled else { return false } - if let accessibilityAction { - accessibilityAction(self) - return true - } else { - return super.accessibilityActivate() - } +// if #available(iOS 17, *) { +// if let block = accessibilityAction { +// block(self) +// return true +// } else if let block = accessibilityActivateBlock { +// return block() +// +// } else if let block = bridge_accessibilityActivateBlock { +// return block() +// +// } else { +// return super.accessibilityActivate() +// +// } +// +// } else { + if let block = accessibilityAction { + block(self) + return true + + } else if let block = bridge_accessibilityActivateBlock { + return block() + + } else { + return super.accessibilityActivate() + + } +// } } //-------------------------------------------------- diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index 4c2aa694..8018e260 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -70,3 +70,86 @@ extension ViewProtocol where Self: UIControl { }).store(in: &subscribers) } } + +public protocol AccessibilityUpdatable { + // Basic accessibility + var bridge_isAccessibilityElementBlock: AXBoolReturnBlock? { get set } + + var bridge_accessibilityLabelBlock: AXStringReturnBlock? { get set } + + var bridge_accessibilityValueBlock: AXStringReturnBlock? { get set } + + var bridge_accessibilityHintBlock: AXStringReturnBlock? { get set } + + var bridge_accessibilityActivateBlock: AXBoolReturnBlock? { get set } + +} + +extension NSObject: AccessibilityUpdatable { + static var isAccessibilityElementBlockKey: UInt8 = 0 + static var activateBlockKey: UInt8 = 1 + static var valueBlockKey: UInt8 = 2 + static var hintBlockKey: UInt8 = 3 + static var labelBlockKey: UInt8 = 4 + + public var bridge_isAccessibilityElementBlock: AXBoolReturnBlock? { + get { + return objc_getAssociatedObject(self, &NSObject.isAccessibilityElementBlockKey) as? AXBoolReturnBlock + } + set { + objc_setAssociatedObject(self, &NSObject.isAccessibilityElementBlockKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// if #available(iOS 17, *) { +// self.isAccessibilityElementBlock = newValue +// } + } + } + + public var bridge_accessibilityActivateBlock: AXBoolReturnBlock? { + get { + return objc_getAssociatedObject(self, &NSObject.activateBlockKey) as? AXBoolReturnBlock + } + set { + objc_setAssociatedObject(self, &NSObject.activateBlockKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// if #available(iOS 17, *) { +// self.accessibilityActivateBlock = newValue +// } + } + } + + public var bridge_accessibilityValueBlock: AXStringReturnBlock? { + get { + return objc_getAssociatedObject(self, &NSObject.valueBlockKey) as? AXStringReturnBlock + } + set { + objc_setAssociatedObject(self, &NSObject.valueBlockKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// if #available(iOS 17, *) { +// self.accessibilityValueBlock = newValue +// } + } + } + + public var bridge_accessibilityHintBlock: AXStringReturnBlock? { + get { + return objc_getAssociatedObject(self, &NSObject.hintBlockKey) as? AXStringReturnBlock + } + set { + objc_setAssociatedObject(self, &NSObject.hintBlockKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// if #available(iOS 17, *) { +// self.accessibilityHintBlock = newValue +// } + } + } + + public var bridge_accessibilityLabelBlock: AXStringReturnBlock? { + get { + return objc_getAssociatedObject(self, &NSObject.labelBlockKey) as? AXStringReturnBlock + } + set { + objc_setAssociatedObject(self, &NSObject.labelBlockKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// if #available(iOS 17, *) { +// self.accessibilityLabelBlock = newValue +// } + } + } + +}