how do i make UIKeyInput make repeated deleteBackwards calls - ios

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.

Related

Passing data between more than 2 viewcontrollers in Swift

My app contains TabBar controller with 5 viewcontrollers. It is possible to click on a button in each of viewcontrollers which will popup another view in which user can choose a setting. The button (which was clicked) is supposed to change its background according to chosen setting in each viewcontroller. So if the user clicks on button in VC1 and chooses the setting, this information should spread into all of the other VCs so that the button has the same background.
I am using storyboards, and I know that this is easily possible between 2VCs using segues, protocols, closures... I cannot find a proper way to spread information to more than 2VCs.
The only solution I can think of is usage of UserDefaults. I would save an information about a button setting and then call ViewWillAppear in each VC, where the background of the button would be set according to the value in UserDefaults. Is there a better solution, please?
EDIT:
As #cora mentioned in the comments, I was able to solve this using Notification Center.
You have several options, including:
Pass an array of the tab controllers to your "popup settings" controller and call a "settingSelected" func in each one directly.
Using Protocol / Delegate pattern, you could create an array of delegates in your "popup settings" controller.
You can use Notification Center.
You could subclass the button and use UIAppearance proxy.
Which approach to use will depend on a number of factors, based on exactly what all you need to do (are there other "settings"? or only that button background?)
You may want to search for swift using themes to see various different approaches.
“Is there a better solution, please?”
Not necessarily. Is this in fact a user default, to be preserved between launches? Then this is exactly what user defaults are for.
If not, then at least you need some central location where information about the current button color can be stored. An obvious candidate here is the tab bar controller itself. It gets notified every time there is a tab bar item switch, so it’s a perfect candidate.
Since you have mentioned you are using a UITabbarController, you can use an instance of UITabbarController and then access .viewControllers property of it and call their added public methods to get them triggered on events that you add. Additionally, using Notification Center makes more sense to me since your code will be more readable. Sometimes Notifications can just get a little confusing for new developers who are working on your code.

UIAccessibility - containers

There's a "Containers" rotor option in Voiceover which allows the user to quickly navigate through "high level" sections of the screen via single finger swipe up and swipe down actions. For example, the Calendar app has three high level items: navbar, contents and toolbar.
My app uses custom UIView subclasses and, no matter what I try to do, all my views seem to belong to a single container. I can't split them into logical sections. I tried putting them in separate views implementing the UIAccessibilityContainer protocol and setting a few of the accessibility properties on the parent views.
Does anyone know how to create multiple containers?
I did some digging on this issue and think its a private trait Apple is using. First I noticed the only containers recognized are standard UIKit type objects like UITableViews, UITabBars, UINavigationBars, etc. So next I used the debugger to inspect the value of the accessibility traits for these components. They're all 0x200000000000. Just to be sure I didn't miss an UIAccessibilityTrait I checked all of their values. None of them match the value. Furthermore if you set your views accessibility traits to this mysterious value it'll work just like you want! I tried determining the location of this constant but didn't have much luck. If you want to do more digging it looks like apple stores accessibilityTraits using an NSObject category that uses associated objects with some constant value named AXTraitsIdentifier.
Practically speaking you could do something like the below but since its not defined in a public API its functionality could change in the future
//Note the navBar has to be run through a voice over pass before the value is set :( or you can just directly set the value to 0x200000000000.
myContainerView.accessibilityTraits = navBar.accessibilityTraits;
I'd love to hear if anyone one else has info on this? So far I haven't found an ideal solution.
I have been able to make the views in my app reachable by single finger swipe up and swipe down actions when the "Containers" rotor option is selected by setting the accessibilityContainerType property of my views to semanticGroup.

IOS 8:custom Keyboard with undo and redo button

I have developed an IOS 8 custom keyboard. I want to give it "undo" and "redo" functionality, like the default system keyboard. I have tried it in different ways but was unable to find a good solution.
We can interact with a Text Input Object textDocumentProxy with the methods
insertText
deleteBackward
documentContextAfterInput
ocumentContextBeforeInput
But I was unable to find any way of implementing "undo" and "redo" functionality.
I think we can NOT implement these function (undo,redo)
According to https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/Keyboard.html
Because a custom keyboard can draw only within the primary view of its
UIInputViewController object, it cannot select text. Text selection is
under the control of the app that is using the keyboard. If that app
provides an editing menu interface (such as for Cut, Copy, and Paste),
the keyboard has no access to it. A custom keyboard cannot offer
inline autocorrection controls near the insertion point.
I think there are many case that content of textfield changed and you can not know when it changed, how it changed. If we can not know, we can not know to undo to where too. I think so.
I'm developing Custom keyboard extension like you and I have many problems. (eg: how can we know the current cursor to get current text selection...)
My question: Current text selection in CustomKeyBoardExtension (hope somebody know)

How do I get the currently focused element when using VoiceOver on 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

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.

Resources