I want to use the autocorrection and shortcut list like default English keyboard with my custom keyboard. I check the in keyboard document but don\'t know how to use it.
Every custom keyboard (independent of the value of its RequestsOpenAccess key) has access to a basic autocorrection lexicon through the UILexicon
class. Make use of this class, along with a lexicon of your own design, to provide suggestions and autocorrections as users are entering text. The UILexicon object contains words from various sources, including:
Unpaired first names and last names from the user’s Address Book database Text shortcuts defined in the Settings > General > Keyboard > Shortcuts list A common words dictionary that includes the names of Apple products
Actually, UILexicon
is just a way to get some user-specific words that your spellchecking system should't try to fix. Probably, the most common way to use it is to fill out UITextChecker
's list of ignored words.
let lexicon: UILexicon = ...
let checker: UITextChecker = ...
for entry in lexicon.entries {
if entry.documentText == entry.userInput {
checker.ignoreWord(entry.documentText)
}
}
Additionally, UILexicon
can be used as source of autoreplaced shortcuts like ("omw" = "On my way!"), but it is not autocorrection in terms of spelling.
Implementing the lexicon would look pretty much like this:
requestSupplementaryLexiconWithCompletion()
to get the lexicon upon launch once.NSString
(tracking the current word)Additionally you could also use UITextChecker
to offer more advanced auto-correct features.
Code (in Objective-C, this may not be 100% accurate I wrote in SO while on the bus but it should do):
UILexicon *lexicon;
NSString *currentString;
-(void)viewDidLoad {
[self requestSupplementaryLexiconWithCompletion:^(UILexicon *receivedLexicon) {
self.lexicon = receivedLexicon;
}];
}
-(IBAction)myTypingAction:(UIButton *)sender {
[documentProxy insertText:sender.title];
[currentString stringByAppendingString:sender.title];
}
-(IBAction)space {
[documentProxy insertText:@" "];
for (UILexiconEntry *lexiconEntry in lexicon.entries) {
if (lexiconEntry.userInput isEqualToString:currentString) {
for (int i = 0; currentString.length >=i ; i++) {
[documentProxy deleteTextBackwards];
}
[documentProxy insertText:lexiconEntry.documentText];
currentString = @"";
}
}
}
Feel free to comment if you have any more questions.
Source: Personal experience with iOS 8 keyboards and UILexicon
Although I have not personally tried creating a custom keyboard, I am basing this answer on what I can see in the documentation.
In your keyboard, create a property called entries
of type [AnyObject]
(Array of AnyObjects).
In your init
method, or wherever you create the keyboard, call this method:
requestSupplementaryLexiconWithCompletion(completionHandler: {
lexicon in
self.entries = lexicon.entries
})
I suspect that entries
is actually an array of Strings or NSStrings, but it could be a dictionary or some other type. When testing this out, try figuring out what type is actually contained in entries
before figuring out your logic.
I do not believe there is a way to get Apple's default autocorrect options currently. However, this WWDC talk gives insight about how they made autocorrect work in the original iPhone OS (around the 30 minute mark).
He mentions using a binary search of the array, which leads me to believe that this array is sorted. Of course, much could have changed since the first iPhone came out...
Good luck figuring out this new API!
With regards to auto-correction, I was able to add it using link. Here's the code snippet I used from the link:
UITextChecker *checker = [[UITextChecker alloc] init];
NSRange checkRange = NSMakeRange(0, self.txView.text.length);
NSRange misspelledRange = [checker rangeOfMisspelledWordInString:self.txView.text
range:checkRange
startingAt:checkRange.location
wrap:NO
language:@"en_US"];
NSArray *arrGuessed = [checker guessesForWordRange:misspelledRange inString:self.txView.text language:@"en_US"];
self.txView.text = [self.txView.text stringByReplacingCharactersInRange:misspelledRange
withString:[arrGuessed objectAtIndex:0]];
The full documentation from Apple can be found here.
Rachits answer above in swift 4. Works with iOS 12
I have this helper to check wether the current string to be tested by UITextChecker is not a space
func validate(string: String?) -> Bool {
guard let text = string,
!text.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty else {
return false
}
return true
}
The text checker is then in my "Spacebar", "Spacebar double tapped" & "return" methods. The example below is in my "Space" method
let textChecker = UITextChecker()
let currentString = self.textDocumentProxy.documentContextBeforeInput
if validate(string: currentString) {
let charSet = NSCharacterSet.whitespacesAndNewlines
let components = currentString?.components(separatedBy: charSet)
let lastWord = components?.last
let checkRange = NSMakeRange(0, lastWord?.count ?? 0)
let misspelledRange = textChecker.rangeOfMisspelledWord(in: lastWord!, range: checkRange, startingAt: checkRange.location, wrap: false, language: "en_US")
if misspelledRange.length != 0 {
let guessedWord: Array = textChecker.guesses(forWordRange: misspelledRange, in: lastWord!, language: "en_US")!
if guessedWord.count > 0 {
var i = 0
while (lastWord?.length)! > i {
textDocumentProxy.deleteBackward()
i += 1
}
self.textDocumentProxy.insertText(guessedWord[0])
}
}
}
self.textDocumentProxy.insertText(" ")
I had to make two changes to Rachits code. First to validate the currentString since it throws an exception if you press space bar twice. And second to check if the misspelled range is not 0 because that was also throwing an exception which I am yet to figure out why. But this works for me now as is.