Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributedLabel Accessibility Links #537

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

RoyalPineapple
Copy link
Collaborator

@RoyalPineapple RoyalPineapple commented Jan 22, 2025

This PR migrates AttributedLabel's link rotor from a stateful to functional pattern, eliminating the need for two variables and preventing voiceover from getting out of sync.

I also fixed a bug in links(at location: CGPoint) that could cause a crash if the AttributedString lacked a specified NSTextAlignment.

@RoyalPineapple RoyalPineapple changed the title [WIP] [DNR] playing with some rotor helpers [WIP] [DNR] AttributedLabel Links Rotor Jan 23, 2025
@@ -389,7 +364,7 @@ extension AttributedLabel {
}

assert(
alignments.count == 1,
Copy link
Collaborator Author

@RoyalPineapple RoyalPineapple Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was causing a crash in the demo app.
Someone went through the trouble of writing the nil case below, it'd be a shame never to use it.

@RoyalPineapple RoyalPineapple changed the title [WIP] [DNR] AttributedLabel Links Rotor AttributedLabel Accessibility Links Jan 23, 2025
@RoyalPineapple RoyalPineapple force-pushed the alex/RotorAdditions branch 2 times, most recently from e5ccc90 to 91e208b Compare January 23, 2025 18:27
private var accessibilityLinkIndex = -1

/// These elements need to be retained by the view, and cannot be created inside the
/// `accessibilityCustomRotors` getter.
Copy link
Collaborator Author

@RoyalPineapple RoyalPineapple Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This concern about the elements being retained is still valid. We cannot pass back unretained elements created within the itemSearchBlock.

The trick here is the elements are now retained in an array which is itself captured by the itemSearchBlock.

Once VoiceOver releases the rotor these elements all get deallocated and then will be recreated the next time VoiceOver requests the rotor.

@RoyalPineapple RoyalPineapple marked this pull request as ready for review January 23, 2025 18:56
@RoyalPineapple RoyalPineapple requested a review from a team as a code owner January 23, 2025 18:56
extension BidirectionalCollection where Element: Equatable, Element: NSObjectProtocol {
private func itemSearch(_ predicate: UIAccessibilityCustomRotorSearchPredicate) -> UIAccessibilityCustomRotorItemResult? {
guard let first else { return nil }
guard let currentItem = predicate.currentItem.targetElement as? Element,
Copy link
Collaborator

@kyleve kyleve Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking outloud, im surprised to see both the generic constraint and this dynamic check; are both required?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants