iPhone: Disable the "double-tap spacebar for ." shortcut?
By default, if you tap the spacebar twice on the iPhone or iPad, instead of getting " " (two spaces), you get ". " (a period followed by a space). Is there any way to disable this shortcut in code?
Update: Disabling autocorrection via UITextInputTraits doesn't work.
Update 2: Got it! See my post below.
Solution 1:
I have an answer based on the the one given by Chaise above.
Chaise's method does not allow you to type two spaces in sequence - this is not desirable in some situations. Here's a way to completely turn off the auto-period insert:
Swift
In the delegate method:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
//Ensure we're not at the start of the text field and we are inserting text
if range.location > 0 && text.count > 0
{
let whitespace = CharacterSet.whitespaces
let start = text.unicodeScalars.startIndex
let location = textView.text.unicodeScalars.index(textView.text.unicodeScalars.startIndex, offsetBy: range.location - 1)
//Check if a space follows a space
if whitespace.contains(text.unicodeScalars[start]) && whitespace.contains(textView.text.unicodeScalars[location])
{
//Manually replace the space with your own space, programmatically
textView.text = (textView.text as NSString).replacingCharacters(in: range, with: " ")
//Make sure you update the text caret to reflect the programmatic change to the text view
textView.selectedRange = NSMakeRange(range.location + 1, 0)
//Tell UIKit not to insert its space, because you've just inserted your own
return false
}
}
return true
}
Now you can tap the spacebar as much and as fast as you like, inserting only spaces.
Objective-C
In the delegate method:
- (BOOL) textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text
Add the following code:
//Check if a space follows a space
if ( (range.location > 0 && [text length] > 0 &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[text characterAtIndex:0]] &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[[textView text] characterAtIndex:range.location - 1]]) )
{
//Manually replace the space with your own space, programmatically
textView.text = [textView.text stringByReplacingCharactersInRange:range withString:@" "];
//Make sure you update the text caret to reflect the programmatic change to the text view
textView.selectedRange = NSMakeRange(range.location+1, 0);
//Tell Cocoa not to insert its space, because you've just inserted your own
return NO;
}
Solution 2:
This is the simplest solution I could get working for this problem in Swift 4. It's more complete than some other answers as it allows multiple spaces in a row to be entered.
func disableAutoPeriodOnDoubleTapSpace() {
textField.addTarget(self, action: #selector(replaceAutoPeriod), for: .editingChanged)
}
@objc private func replaceAutoPeriod() {
textField.text = textField.text.replacingOccurrences(of: ". ", with: " ")
}
If your text field is formatted with .attributedText, you will need to store the old .selectedTextRange before and reset it after you set the .text value. Otherwise your cursor will move to the end of the text when editing in the middle of a string.
Hope this helps someone who tried all the other answers with no luck!
Solution 3:
Put this in your delegate class:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
//Check for double space
return !(range.location > 0 &&
[string length] > 0 &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[string characterAtIndex:0]] &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[[textField text] characterAtIndex:range.location - 1]]);
}