How do I get the currently focused element when using VoiceOver on iOS? - ios

I have a table with cells that the user may swipe to mark them "completed". I am trying to make this accessible using VoiceOver by implementing the accessbilityScroll method.
This works fine, but I can't figure out what cell has focus when the user scrolls.
I only find information on how to change focus.

Hehe, Ok. I just figured it out.
There is a protocol for this. Its called UIAccessibilityFocus
Method: accessibilityElementDidBecomeFocused:
Well, I will leave this question here to any one else that is out there struggling with this.

Your program can also tell where VoiceOver’s “focus” (the object that it’s dealing with) is, and when “focus” enters or leaves any given object.
For Focus Information click here
– accessibilityElementDidBecomeFocused
– accessibilityElementDidLoseFocus
– accessibilityElementIsFocused

As of iOS9, you can use
UIAccessibilityFocusedElement(UIAccessibilityNotificationVoiceOverIdentifier)
https://developer.apple.com/documentation/uikit/1615119-uiaccessibilityfocusedelement

Related

TableView didSelectRowAtIndexPath not called

So I have added a UIUITableView to a UIViewController. I can't use a UITableViewController for reasons I don't need to explain since it will be unnecessary information. Anyway, I have set the delegate, and the data source to this viewController. I've added the delegate and datasource protocols as well. The cells are populated correctly, so the datasource is working fine. I can also scroll so it all works fine.
However, I can't get the didSelectRowAtIndexPath to trigger. It SHOULD trigger, but doesn't. I've read and a lot of issues with this can be correlated to a UIGestureRecognizer, but I haven't implemented one. I also use the standard UITableView, so not a custom made one.
If I long press the cells (3-4 sec) then it gets triggered as it's supposed to. This suggests that there is some issue with another view or something absorbing the tap gesture, which I have no control over. How would I solve this?
No, it's not didDeselectRowAtIndexPath.
Yes all delegates and datasources are correct, since I can get the delegates/sources to trigger.
Yes, Single Selection is set on the TableView in the inspector.
Yes, everything has user interaction enabled.
If I just copy the code over to a UITableViewController it will work just fine, but right now that is not an option, I'm afraid. Anyone got any ideas on how to solve this? Most people who've had this issue has either had the issues in the list above, or added a UIGesture on top of the UITableView - I haven't.
I want to start by saying that I appreciate all the answers here provided, it gave me a lot of things to try out so I learned a lot - thanks! None of your suggestions worked, but simply because I'm a complete idiot. I said in the post that I did NOT implement a UIGestureRecognizerwhich I didn't...in that class, but in its super class. So I DID in fact implement it, but in a class that this ViewController was a subclass off. The only reason I didn't remember it was because I haven't looked at that super class for weeks.
Someone did suggest it in the comments that I should check for it, and I did and I was already certain I didn't implement one, so I quickly dismissed it. But now, after about 4 hours of debugging and recreating the project, adding things one by one, I eventually realized that the only thing that differed at this point was the Super Class, and the first piece of code I see when I open the file up was a GestureRecognizer...
So keep this in mind in the future everyone - I know I will. Thanks again for the help!
Sincerely,
The complete idiot.
Make sure you don't add any controller in that cell, which covers the entire cell and also the user interaction of that controller is enabled.
Due to that controller's user interaction enabled the tap action is taken by that controller and when you long press that cell, that cell will receive your tap.
Example :
UIView *_view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _cellWidth, _cellHeight)];
[_view setUserInteractionEnabled:YES];
[cell.contentView addSubview:_view];
In the above case that view got your tap instated of the cell.

When are selectionWillChange: and selectionDidChange: called?

I am developing custom keyboard extension in iOS, and I'm wondering when the two UITextInputDelegate methods (selectionWillChange: and selectionDidChange:) called? Has someone tried to implement these two methods and made them work?
According to this
selection did change is called when the user takes the current highlighted text and replaces the whole thing or part of it. The selection will change is what it is going to change into before the did change event is fired.

Moving Accessibility Voiceover cursor focus to a specific element

I'm having an issue with moving the voiceover cursor to a specific element on viewDidAppear. I followed Apple's guidelines for focusing on a specific element, in this case a dismiss button, but the cursor ends up elsewhere
Here is my Code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
self.dismissButton);
}
Any help, ideas, would definitely be appreciated! thank you so much.
If I remember correctly i was not able to reliably focus on elements on first of the view as VO will generally focus on the top of the view.
The code you are doing is correct, but at this point the system will trigger it's own event and override yours.
What you can try to do is post a notification with a delay. But that will result in focus jumping around a little bit when opening the view.
It's not much of an answer, but that is where I'm at at the moment. I'll update you if I figure out a way to do it.
This answer may be of help.
Basically you need to wrap your elements in a container view if they're not in one already and then override the methods specified.
By giving your desired element a tag that is lower than the other elements you can have the view sort the array to ensure that it will be the first element in the accessibilityElements array used by VoiceOver. Or you can adapt the sort method to sort another way.
FYI: As of iOS 11, both UIAccessibilityScreenChangedNotification and UIAccessibilityLayoutChangedNotification reliably focus Voice Over elements for me.

How can I get the size of the keyboard on iPhone?

I want to get the keyboard size without using NSNotification. When I press the plus button, it can replace the keyboard with a custom UIView like this:
Then the plus button is pressed and the view loaded:
How can I achieve this?
I already made same rookie mistake like you want to do here. The problem is you will write a lot only to realize you do not want to avoid standard flow provided you by iOS team. For example you will definitely have a bad time dealing with issue like this one (there is additional bar which is part of standard keyboard for Chinese locale):
I solved this by using other people's work from DAKeyboardControl project. You do not need to attach observer (or if you use DAKeyboardControl - block) directly to your bar with buttons, but to your controller and check what user is trying to do and animate this bar accordingly. In the sources you can see how to get keyboard's animation duration and timing function. It may sound more complicated than it indeed is, just give it a try.

how do i make UIKeyInput make repeated deleteBackwards calls

Currently I am using UIKeyinput but it is only sending a single delteBackward event even when I hold down the delete key for a long time.
How can I make it send me multiple event calls when I hold delete down for a long time?
There is no easy way to have the system keyboard do auto-repeat. These leaves you with two options:
Fake it by using an overlay on the keyboard (see the comment by #pho0)
Implement a custom keyboard, install it as the inputView for your view or view controller and implement a custom protocol that supports auto-repeat.
Solution 1 works well if you only need the delete key to auto-repeat, but if you need all the keys to auto-repeat the overlay code becomes as complex as the custom keyboard option. (The overlay needs a rectangle for each key, so why not just replace the underlaying keyboard).
Solution 2 involves a certain amount of "up-front" work... One way you might do this is define a key cap class (like a physical key) and a keyboard layout class.
I have implemented both solutions in projects I have worked on, but I currently use solution 2 since I can create whatever keyboard I like. In the simple case the use need never know that it is not the system keyboard. For power users they can customize the keyboard as they see fit.
For what it is worth, I found it useful to have the keyboard class be dumb; it just communicates that a key has transitioned to being down or has transitioned to being up. An additional class above that decides what action should be taken.
In some ways, I know this is not the answer you were looking for, but I hope it helps,
IDZ
One thing I've seen people do is put a fake button on top of the keyboard button. When someone is holding down on it, have a timer remove the last letter every time it fires.
Hope this helps.

Resources