Limit text field length - objective-c

Please tell me how I can set the range of a text field to a maximum of six and minimum of one.

Set self as textfield's delegate and implement this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newString.length < 1) {
// too short
} else if (newString.length > 6) {
// too long
}
return YES;
}
I'd suggest you to have a UILabel that will say in red text that text is too short or too long. Just preventing user from typing into textfield when they reach 6 chars or deleting last character when they change their mind is a very bad user experience.

Implement the delegate method textField:shouldReplaceCharactersInRange:replacementString: and have your implementation return NO if the resulting string would fall outside of your constraints.

Related

How to find a particular text in UITextField?

In my iPhone app I have a UITextField ans text field value is being taken into an NSString, I want to find if a particular character " is typed in that
How can I do that?
UITextField *textField;
NSString *String=textField.text;
-(IBAction)FindCharecter:(id)sender
{
// if String Contain ",then i wish to print #"Found symbol"
}
UITextField *textField;
NSString *string=textField.text;
if ([string rangeOfString:#"\""].location == NSNotFound) {
NSLog(#"string does not \"");
} else {
NSLog(#"string contains \"");
}
check this
Try This:
-(IBAction)FindCharecter:(id)sender
{
// if String Contain ",then i wish to print #"Found symbol"
if ([String rangeOfString:#"\""].location != NSNotFound) {
NSLog(#"Found");
}
else{
NSLog(#"Not Found");
}
}
Implement the following delegate of UITextField
-(NSString *)ValidateSearchString:(NSString *) aString{
NSCharacterSet * set = [[NSCharacterSet characterSetWithCharactersInString:#"YourString"] invertedSet];
if ([aString rangeOfCharacterFromSet:set].location != NSNotFound) {
return #"Not Found";
}
return #"Found";;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSLog("particular character %#",[self ValidateSearchString:string]);
// string will contain the particular character typed;
return YES;
}
You need to confirm and implement UITextFieldDelegate protocol.
1) If you want to check for a pattern on the go (when user typing itself), you need to implement
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
2) If you want to check when user completed typing, you may want to implement
- (void)textFieldDidEndEditing:(UITextField *)textField
Now to do the actual comparison process
if([textFieldString rangeOfString:#"YOUR_COMPARISON_STRING"].location == NSNotFound){
//your pattern is not typed yet
}else{
//There it is..
}
You can use shouldChangeCharactersInRange delegate method for this.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([string isEqualToString:#"\""])
{
NSLog(#"Entered \" ");
}
}
Or you can use: rangeOfString of NSString class.
if ([textField.text rangeOfString:#"\""].location == NSNotFound)
{
NSLog(#"Entered \" ");
}
For reference:
textField:shouldChangeCharactersInRange:replacementString:
Asks the delegate if the specified text should be changed.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Parameters
textField
The text field containing the text.
range
The range of characters to be replaced
string
The replacement string.
Return Value
YES if the specified text range should be replaced; otherwise, NO to
keep the old text. Discussion
The text field calls this method whenever the user types a new
character in the text field or deletes an existing character.
Availability
Available in iOS 2.0 and later.
UITextFieldDelegate
rangeOfString:
Finds and returns the range of the first occurrence of a given string
within the receiver.
- (NSRange)rangeOfString:(NSString *)aString
Parameters
aString
The string to search for. This value must not be nil.
Important: Raises an NSInvalidArgumentException if aString is nil.
Return Value
An NSRange structure giving the location and length in the receiver of
the first occurrence of aString. Returns {NSNotFound, 0} if aString is
not found or is empty (#"").
Discussion
Invokes rangeOfString:options: with no options.
This method detects all invalid ranges (including those with negative
lengths). For applications linked against OS X v10.6 and later, this
error causes an exception; for applications linked against earlier
releases, this error causes a warning, which is displayed just once
per application execution. Availability
Declared In NSString.h
Declared In UITextField.h
NSString Class

How to set max string length for UIAlertView text field

How can I set the max string length for a textfield created within a UIAlertView? I am using Xcode 4.5 and building the app on 10.8 (OS X) Currently I have UIAlertView that launches when the user clicks a button. The user will scan their RFID badge, and I want the input textfield of the UIAlertView to be limited to 10 (ten) characters so the user can't fudge association process.
You can check the length of the text in the delegate method of the textField:
textField:shouldChangeCharactersInRange:replacementString:
And return NO if you don't want to change.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.text.length - range.length + string.length > 10) {
return NO;
}
return YES;
}
Looks like the above answer is almost right.
When typing single characters, range.length (for this method) appears to always be zero, while the location increments.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSLog(#"Range: %#", NSStringFromRange(range));
return ( range.location < 10 );
}
edit: length would probably be longer if you doing something other than single-character typing, i.e. pasting a line, etc.

Character limit for multiple uitextfields

I'm a fairly new programmer and am having trouble with some UITextfields, basically i have two text fields and i want to limit the amount of characters in one of them to a certain amount, whilst allowing the other field to have lots.
I found a post that recommended this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSUInteger newLength = [[textField text] length] + [string length] - range.length;
return (newLength > 2) ? NO : YES;
}
However that seems to affect both text fields. I'm not sure how to target one field.
Can anyone help, also one thing, i get whats going on in that code up until - range. length, is the range the total amount of characters?
Ok so the issue here is that the object which contains this code is the delegate to both textfields. Two ways to solve it. Either dont add the textfield you dont care about the length of as a delegate or the better way would be to differentiate between the fields during the shouldChangeCharactersInRange method.
For the second part of your question- range is the character(s) that is/are being changed in the text field and consists of: The position of the string to change, the length of the string being changed.
My personal preference is to say if the text length is greater than max length and your not deleting then refuse the change.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(textField == self.textfieldYouWantToLimitTheLengthOf){
if(textField.text.length > 2 && ![string isEqualToString:#""]){
return NO;
}
}
return YES;
}

Knowing the complete changed string in textField:shouldChangeCharactersInRange:replacementString:

I just asked a question about how to monitor changes to a UITextField and received this response :
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)replacementStr {
// Enable "Next" if you like what's entered in the replacementStr
}
This works, but the replacement string is not the whole string, just what it is adding. How can I get the whole string? My objective is to see if the string in the text field is blank or equal to a certain number (in different scenarios).
Please note that the outlet to the text field doesn't work in this case, because this method is being called before the text in the field changes.
NSString * proposedNewString = [[textField text] stringByReplacingCharactersInRange:range withString:replacementString];
Swift Version
In Swift We need to cast textField's text to NSString. The following can be useful:
let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];
// [textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
NSLog(#"%#",searchStr);
return YES;
}

Make portion of UITextView undeletable

I have a UITextView and need to make a specific portion un-deletable. Its the first 10 characters of the views text.
I just want it so that if the user is tapping the delete key on the keyboard it simply stops when it reaches say the 10th character in.
Edit
Let me go into a bit more detail.
Let's say the prefix is '123456789:'. I want to be able to type anywhere after this prefix, it can't be editable at all though, so '123456789:' shouldn't not be altered at all. Fichek's answer does this perfectly, however the prefix isn't always there, so how can I detect when it isn't in the textview? I thought the if statement did this but it seems not to.
You can use the delegate method textView:shouldChangeTextInRange:replacementText: To tell the text view whether to accept the delete or not.
As the documentation says:
range : The current selection range. If the length of the range is 0, range reflects the current insertion point. If the user presses the Delete key, the length of the range is 1 and an empty string object replaces that single character.
Edit
Here is an implementation where the user can't delete the the first ten characters. But he will be able to insert characters there.
- (BOOL)textView:(UITextView *)textView shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (range.length==1 && string.length == 0) {
// Deleting text
if (range.location <= 9) {
return NO;
}
}
return YES;
}
Here is an implementation where he can't modify the first ten characters at all.
- (BOOL)textView:(UITextView *)textView shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (range.location <= 9) {
return NO;
}
return YES;
}
sch's last edit makes a decent answer, but I want to offer a slightly more flexible approach.
You have to keep in mind the copy/paste system. User might select all the text in text field and try to paste in the entire value which might be perfectly acceptable, but if (range.location <= 9) { return NO; } will reject it. The way I'd do it is put together a string that would be a result of successful edit and then check if that string would start with your desired prefix.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(#"resulting string would be: %#", resultString);
NSString *prefixString = #"blabla";
NSRange prefixStringRange = [resultString rangeOfString:prefixString];
if (prefixStringRange.location == 0) {
// prefix found at the beginning of result string
return YES;
}
return NO;
}
Edit: if you want to check if the current string in text field starts with the prefix, you can use rangeOfString: the same way:
NSRange prefixRange = [textField.text rangeOfString:prefixString];
if (prefixRange.location == 0) {
// prefix found at the beginning of text field
}
for a complete solution you need to handle several cases, including the cut and paste operations that may start in the uneditable part and extend into the part which the user can edit. I added a variable to control whether or not an operation that includes the uneditable part but extends into the editable part, is valid or not. If valid, the range is adjusted to only affect the editable part.
// if a nil is returned, the change is NOT allowed
- (NSString *)allowChangesToTextView:(UITextView *)textView inRange:(NSRange)changeRange withReplacementText:(NSString *)text
immutableUpTo:(NSInteger)lastReadOnlyChar adjustRangeForEdits:(BOOL)adjustRangeForEdits;
{
NSString *resultString = #"";
NSString *currentText = textView.text;
NSInteger textLength = [currentText length];
// if trying to edit the first part, possibly prevent it.
if (changeRange.location <= lastReadOnlyChar)
{
// handle typing or backspace in protected range.
if (changeRange.length <= 1)
{
return nil;
}
// handle all edits solely in protected range
if ( (changeRange.location + changeRange.length) <= lastReadOnlyChar)
{
return nil;
}
// if the user wants to completely prevent edits that extend into the
// read only substring, return no
if (!adjustRangeForEdits)
{
return nil;
}
// the range includes read only part but extends into editable part.
// adjust the range so that it does not include the read only portion.
NSInteger prevLastChar = changeRange.location + changeRange.length - 1;
NSRange newRange = NSMakeRange(lastReadOnlyChar + 1, prevLastChar - (lastReadOnlyChar + 1) + 1);
resultString = [textView.text stringByReplacingCharactersInRange:newRange withString:text];
return resultString;
}
// the range does not include the immutable part. Make the change and return the string
resultString = [currentText stringByReplacingCharactersInRange:changeRange withString:text];
return resultString;
}
and this is how it gets called from the text view delegate method:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
// did the user press enter?
if ([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
return NO;
}
NSInteger endOfReadOnlyText = [self.spotTextLastSet length] - 1;
NSString *newText = [self allowChangesToTextView:textView inRange:range withReplacementText:text
immutableUpTo:endOfReadOnlyText adjustRangeForEdits:YES];
if (newText == nil)
{
// do not allow!
[TipScreen showTipTitle:#"Information" message:#"The first part of the text is not editable. Please add your comments at the end."
ForScreen:#"editWarning"];
return NO;
}
// lets handle the edits ourselves since we got the result string.
textView.scrollEnabled = NO;
textView.text = newText;
// move the cursor to change range start + length of replacement text
NSInteger newCursorPos = range.location + [text length];
textView.selectedRange = NSMakeRange(newCursorPos, 0);
textView.scrollEnabled = YES;
return NO;
}