Using `textField:shouldChangeCharactersInRange:`, how do I get the text including the current typed character?
IosObjective CUitextfieldIos Problem Overview
I'm using the code below to try and have textField2
's text content get updated to match textField1
's whenever the user types in textField1
.
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {
if (theTextField == textField1){
[textField2 setText:[textField1 text]];
}
}
However, the output I observe is that...
> textField2 is "12", when textField1 is "123" > > textField2 is "123", when textField1 is "1234"
... when what I want is:
> textField2 is "123", when textField1 is "123" > > textField2 is "1234", when textField1 is "1234"
What am I doing wrong?
Ios Solutions
Solution 1 - Ios
-shouldChangeCharactersInRange
gets called before text field actually changes its text, that's why you're getting old text value. To get the text after update use:
[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Solution 2 - Ios
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(@"%@",searchStr);
return YES;
}
Solution 3 - Ios
#Swift 3
Based on the accepted answer, the following should work in Swift 3:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
return true
}
##Note
Both String
and NSString
have methods called replacingCharacters:inRange:withString
. However, as expected, the former expects an instance of Range
, while the latter expects an instance of NSRange
. The textField
delegate method uses an NSRange
instance, thus the use of NSString
in this case.
Solution 4 - Ios
Instead of using the UITextFieldDelegate, try to use "Editing Changed" event of UITextField.
Solution 5 - Ios
In Swift(4), without NSString
(pure Swift):
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {
let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)
print("FullString: \(fullString)")
}
return true
}
As an extension:
extension UITextField {
func fullTextWith(range: NSRange, replacementString: String) -> String? {
if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {
return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
}
return nil
}
}
// Usage:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
print("FullString: \(textFieldString)")
}
return true
}
Solution 6 - Ios
Swift version for it :
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if string == " " {
return false
}
let userEnteredString = textField.text
var newString = (userEnteredString! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString
print(newString)
return true
}
Solution 7 - Ios
This is the code you need,
if ([textField isEqual:self.textField1])
textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Solution 8 - Ios
use guard
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard case let textFieldString as NSString = textField.text where
textFieldString.stringByReplacingCharactersInRange(range, withString: string).length <= maxLength else {
return false
}
return true
}
Solution 9 - Ios
My solution is to use UITextFieldTextDidChangeNotification
.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(copyText:) name:UITextFieldTextDidChangeNotification object:nil];
Don't forget to call [[NSNotificationCenter defaultCenter] removeObserver:self];
in dealloc
method.
Solution 10 - Ios
If you need to replace the textfield text with this you can use my solution (Swift 3): https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047
After the replacement you can just get textField.text
to retrieve the composed text.