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 the
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]]);
}
Another version of the one simeon posted (which was a version of Chaise's). This one works with text fields (UITextField
). You'll have to set up the UITextFieldDelegate
for this to do anything. I commented out the line for updating the caret, but it still seems to work.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)text
{
//Check if a space follows a space
if ( (range.location > 0 && [text length] > 0 &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[text characterAtIndex:0]] &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[[textField text] characterAtIndex:range.location - 1]]) )
{
//Manually replace the space with your own space, programmatically
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@" "];
//Make sure you update the text caret to reflect the programmatic change to the text view
// textField.selectedTextRange = NSMakeRange(range.location+1, 0);
//Tell Cocoa not to insert its space, because you've just inserted your own
return NO;
}
return YES;
}
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!
OK, I figured it out. In your UITextView delegate, add this:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@". "])
return NO;
}
A simpler solution that I have found to work for a UITextView
is as follows:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:@". "] && range.length == 1) {
NSMutableAttributedString *attributedString = [textView.attributedText mutableCopy];
[attributedString replaceCharactersInRange:range withString:@" "];
textView.attributedText = attributedString;
textView.selectedRange = NSMakeRange(range.location + 1, 0);
return NO;
}
return YES;
}
This allows multiple spaces to be entered repeatedly and also handles attributed text. The only case I have found it to fail with is when pasting a period and space with a single character already selected.
This is an implementation in Swift 4.0 for text fields, copying Simeon's answer:
func textField(_ textField: UITextField, 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
//get list of whitespace characters
let start = text.unicodeScalars.startIndex
if let textFieldText = textField.text{
let location = textFieldText.unicodeScalars.index(textFieldText.unicodeScalars.startIndex, offsetBy: range.location - 1)
//Check if a space follows a space
if whitespace.contains(text.unicodeScalars[start]) && whitespace.contains(textFieldText.unicodeScalars[location]){
//Manually replace the space with your own space, programmatically
textField.text = (textFieldText as NSString?)?.replacingCharacters(in: range, with: " ")
if let pos = textField.position(from: textField.beginningOfDocument, offset: range.location + 1)
{
//Make sure you update the text caret to reflect the programmatic change to the text view
textField.selectedTextRange = textField.textRange(from: pos, to: pos)
//Tell UIKit not to insert its space, because you've just inserted your own
return false
}
}
}
}
return true
}
Hope this helps!
EDIT: Added a missing return statement at bottom.