Objective-c How to do validation on textField - ios

I would like to prevent the user from not entering any data as well as entering only spaces. So basically there must at least be one character without a space. Then I would also like to remove any spaces at the beginning of the word so the first letter is a character that is not a space.
edit
the user must enter something and if the user enters a few spaces before it then I want to trim those spaces. I also want to prevent the user from just entering spaces.
Example
if the user enter's a name and surname like " James Dean" I would like to take the first space away but not the second space between James and Dean.

Set your UIViewController to be your destination UITextField's delegate and implement this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// verify the text field you wanna validate
if (textField == _nameTextField) {
// do not allow the first character to be space | do not allow more than one space
if ([string isEqualToString:#" "]) {
if (!textField.text.length)
return NO;
if ([[textField.text stringByReplacingCharactersInRange:range withString:string] rangeOfString:#" "].length)
return NO;
}
// allow backspace
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length < textField.text.length) {
return YES;
}
// in case you need to limit the max number of characters
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length > 30) {
return NO;
}
// limit the input to only the stuff in this character set, so no emoji or cirylic or any other insane characters
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "];
if ([string rangeOfCharacterFromSet:set].location == NSNotFound) {
return NO;
}
}
return YES;
}

try like this may be it helps to you,here is my code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string{
if([text.text length]==0){
if([string isEqualToString:#" "]){
return NO;
}
}
return YES;
}
By placing this code user won't enter space as a first letter but it accepts the space in the middle of the string.

I'll give you a hint for the first part.
NSString *tempname1 = [self.textField.text stringByReplacingOccurrencesOfString:#" " withString:#""];
BOOL thereAreJustSpaces = [tempname1 isEqualToString:#""];

-(void)removeSpacesFromTextFields:(id) sender {
NSString *trim = [self.FNTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([trim length] == 0) {
self.FNTextField.text = #"";
}
}

Try this, If you want to prevent space in your text field.
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(checkSpace:) name:UITextFieldTextDidChangeNotification object:textfield];
}
-(void)checkSpace:(NSNotification *)notification
{
str = [textfield.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] ;
textfield.text=str;
}

Related

How to force the user to stop typing in UITextField but allow backspacing

I have a UITextField that my user uses to type out tags. I need to be able to at a very specific time - stop my user from continuing to type in the keyboard that is presented by default with UITextFields. However, I need my user to still be allowed to hit the backspace button on the iOS keyboard so that they can try and type a word that will fit.
A couple VERY important things to keep in mind:
The UITextField should not be frozen due to a maximum amount of characters, because I am determining when the textField should be frozen based off of UIViews that I am adding to the screen for the tags
The user still should be able to backspace
The keyboard should not be dismissed
The textField should not be disabled
I have tried setting the textField.enabled = NO, but once again, I need to still be able to use the textField, I just simply need to freeze the typing and force the user to backspace, not allowing andy characters to be added to the textField.
You could try something like below
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString: (NSString*) string {
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
if([text length] > MAX_LENGTH)
return NO;
else
return YES;
}
EDIT1:
To this delegate method get called, set the textfield's delegate.
In this case, you can use it as
yourTextField.delegate = self;
In your viewWillAppear/viewDidAppear.
Try this
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Prevent crashing undo bug – see note below.
if(range.length + range.location > textField.text.length)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
if(textField == self.yourTextField)
{
return newLength <= CHARACTER_LIMIT;
}
else
{
return YES;
}
}
Try this, Back space will work even if the textfield pre populated with more than MAX_Length text
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString: (NSString*) string {
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
if([text length] > MAX_LENGTH && string.length>0)
return NO;
else
return YES;
}

Restrict user to enter abuse words in text view

I am developing a application where user has to enter only holy words. I want user to be restricted not to enter the abuse or adult word.
I have a big list of adult or abuse words whenever user will enter that word it should delete it automatically.
Any help will be appreciated.
You are probably using UITextField so you should look after forbidden words after text has changed:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSRange spaceRange = [newString rangeOfString:#" "];
if (spaceRange.location != NSNotFound) { // it's a new word
newString = [self stringWithoutForbiddenWords:newString];
}
textField.text = newString;
return NO; // we set the textField text manually
}
- (NSString *)stringWithoutForbiddenWords:(NSString *)string {
for (NSString *forbiddenWord in self.forbiddenWords) {
NSRange forbiddenWordRange = [string rangeOfString:forbiddenWord];
if (forbiddenWordRange.location != NSNotFound) {
// remove the forbidden word
string = [string stringByReplacingOccurrencesOfString:forbiddenWord withString:#""];
}
}
return string;
}
Don't forget to set you UITextField delegate.
Its a very simple logic , by the way only "Holy Word" seems very funny I hope you meant non-abusive words.
So to restrict abusive words, first make an Array and store all the abusive words in that.
then in textView shouldChangeTextInRange: check whenever user press " space.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([string isEqualToString:#" "])
{
//now iterate the whole string and find whether any word contains any value from your Abusive words Array and replace the word with blank space or *
}

Adding a constant country code at beginning of UITextField

I have a UITextField that the user require to enter a phone number into it.
This is how it looks like right now:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Auto-add hyphen before appending 4rd or 7th digit
//
//
if (range.length == 0 && (range.location == 3 || range.location == 7))
{
textField.text = [NSString stringWithFormat:#"%#-%#", textField.text, string];
return NO;
}
// Delete hyphen when deleting its trailing digit
//
//
if (range.length == 1 && (range.location == 4 || range.location == 8))
{
range.location--;
range.length = 2;
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:#""];
return NO;
}
// Prevent crashing undo bug – see note below.
//
//
if (range.length + range.location > textField.text.length)
{
return NO;
}
// Limit text field characters
//
//
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 12) ? NO : YES;
}
After the 3rd digit, I'm adding a hyphen and than again. What I'm trying to achieve here is to add a country code as constant at start of the UITextField and that the user will not be able to remove it. Lets say USA country code, then the UITextField text will look like that at start +1- and then after writing the full number it will look like that: +1-600-242-252
How can I do that?
Thanks in advance!
This answer assumes a starting country code string which includes the hyphen at the end, ex: self.countryCode = #"+1-";. The text field should initially contain "+1-".
I've made my answer way more comprehensive than your original intent because it handles many use cases you've overlooked, for example copy and paste operations with multiple characters, inappropriate hyphen deletion, inappropriate hyphen addition, mid-line insertion, etc. It's still not perfect though because your original answer was unspecific in some ways... For example, if you specify that the user should only be able to enter digits, the code can be much cleaner.
The below implementation is described line by line in the comments included throughout.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Combine the new text with the old
NSMutableString *combinedText = [[textField.text stringByReplacingCharactersInRange:range withString:[NSString stringWithFormat:#"%#", string]] mutableCopy];
// If the user deletes part of the country code or tries
// to edit it in any way, don't allow it
if (combinedText.length < self.countryCode.length ||
![combinedText hasPrefix:self.countryCode]) {
return NO;
}
// Limit text field characters to 12
if (combinedText.length > self.countryCode.length + 12) {
return NO;
}
// If the user tries to add a hyphen where there's supposed
// to be a hyphen, allow them to do so.
if ([string isEqualToString:#"-"] &&
(range.location == self.countryCode.length + 3 ||
range.location == self.countryCode.length + 7)) {
return YES;
}
// Remove all the hyphens other than the one directly
// following the country code
[combinedText replaceOccurrencesOfString:#"-" withString:#"" options:0 range:NSMakeRange(self.countryCode.length, [combinedText length] - self.countryCode.length)];
// Auto-add the hyphens before the 4th and 7th digits
if (combinedText.length > self.countryCode.length + 3)
[combinedText insertString:#"-" atIndex:self.countryCode.length + 3];
if (combinedText.length > self.countryCode.length + 7)
[combinedText insertString:#"-" atIndex:self.countryCode.length + 7];
// Store the original cursor position
UITextPosition *pos = [textField selectedTextRange].start;
// Count up the original number of hyphens
NSUInteger originalNumberOfHyphens = [[textField.text componentsSeparatedByString:#"-"] count] - 1;
// Count up the new number of hyphens
NSUInteger newNumberOfHyphens = [[combinedText componentsSeparatedByString:#"-"] count] - 1;
// Create a cursor offset to reflect the difference
// in the number of hyphens
float offset = newNumberOfHyphens - originalNumberOfHyphens;
// Update the text field to contain the combined text
textField.text = combinedText;
// Update the cursor position appropriately
if (string.length > 0) {
UITextPosition* cursor = [textField positionFromPosition:[textField beginningOfDocument] offset:range.location + range.length + offset + string.length];
textField.selectedTextRange = [textField textRangeFromPosition:cursor toPosition:cursor];
} else {
UITextPosition* cursor = [textField positionFromPosition:pos inDirection:UITextLayoutDirectionLeft offset:1-offset];
textField.selectedTextRange = [textField textRangeFromPosition:cursor toPosition:cursor];
}
// No need to replace the string since it's already been done
return NO;
}
To keep a constant at the beginning, you basically want to check if the constant still exist in the proposed text. If it doesn't reject such edits.
You should not try to insert hyphens at specific editing steps. It's better to manipulate the whole string.
E.g.
test if string could be valid. i.e. starts with +1
remove all hyphens you previously added
reinsert all hyphens
In code this would look like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.textField.text = #"+1"; // start with a +1 in the textField otherwise we can't change the field at all
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *proposedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (![proposedText hasPrefix:#"+1"]) {
// tried to remove the first +1
return NO;
}
NSString *formattedPhoneNumber = [proposedText substringFromIndex:2]; // without +1 prefix
NSString *unformattedPhoneNumber = [formattedPhoneNumber stringByReplacingOccurrencesOfString:#"-" withString:#""]; // without hypens
// start with the prefix
NSMutableString *newText = [NSMutableString stringWithString:#"+1"];
for (NSInteger i = 0; i < [unformattedPhoneNumber length]; i++) {
if (i % 3 == 0) {
// add a - every 3 characters. add one at the beginning as well
[newText appendString:#"-"];
}
// add each digit from the unformatted phonenumber
[newText appendString:[unformattedPhoneNumber substringWithRange:NSMakeRange(i, 1)]];
}
textField.text = newText;
return NO;
}
This is still a very naive implementation. It has a couple of problems, for example the cursor will always be at the end because we set text of the textField manually. So the user can't easily remove numbers in the middle of the string. Of course there are ways around this. selectedTextRange would be the property to use. And you can't really paste phone numbers into the field. And of course the user can't delete a hyphen.
Formatting while the user is typing tends to get complicated quickly because there are so many edge cases. But that should get you started.

UITextField auto-delete

When a user holds down the delete key for a certain amount of time, the UITextField begins deleting multiple characters at once. I'm trying to create a UITextField that has a # as the first character. This # should never be deleted. The code below works to prevent the user from deleting the # accept when the user types in many characters, and then proceeds to hold down the delete key until UITextField deletes multiple characters at once. The user is then able to delete all characters from the UITextField despite the logic below. How can this be?
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newLength < 1)
return NO;
else if (newString.length == 0)
return NO;
return (newLength > 30) ? NO : YES;
}
Perhaps something like this would be better:
- (void) textViewDidChange:(UITextView *)textView {
if (![textView.text hasPrefix:#"#"]) {
textView.text = [NSString stringWithFormat:#"#%#", textView.text];
}
}
This way, at any point, if your text view doesn't have a '#' as a prefix, this puts one in. Otherwise, if the user types 10 characters, then goes back and erases the '#' the system won't recognize it, or if they highlight all of the text and erase it. If later code depends on the '#' char, I'd say this is probably more reliable.
I'm not sure if the shouldChangeCharactersInRange method is technically allowed to modify the text field directly, but give this a try and let me know how it goes.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if ( newString.length > 30 )
return( NO );
if ( newString.length < 1 )
newString = #"#";
textField.text = newString; // I'll change the string myself thanks
return( NO ); // string's already changed, don't change it again
}

shouldChangeCharactersInRange logic

I can't seem to figure out the best way to handle this. When user presses decimal point I want it to move to next textfield. The problem I'm having is it's displaying the decimal in the next text field and only works if I type a decimal only. I believe I understand why it's only allowing decimal is because of the way i'm starting if statement, but I can't seem to figure out the best approach here.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *decmial = #".";
if ([textField.text isEqualToString:#"."])
{
if (octet1.text == decmial) {
octet1.text = [octet1.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet1 isFirstResponder];
[octet2 becomeFirstResponder];
}
else if (octet2.text == decmial) {
octet2.text = [octet2.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet2 isFirstResponder];
[octet3 becomeFirstResponder];
}
else if (octet3.text == decmial) {
octet3.text = [octet3.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet3 isFirstResponder];
[octet4 becomeFirstResponder];
}
else if (octet4.text == decmial) {
octet4.text = [octet4.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet4 isFirstResponder];
[myBitMask becomeFirstResponder];
}
}
return YES;
}
Currently, you're only doing anything if the entire content of the text field being modified is exactly ".". I assume that you should really be testing to see if the user has typed that in instead, by comparing with the replacement string:
if ([string isEqualToString:#"."]) {
You then go on to test each of your text fields in turn, without any regard for the actual text field being modified (the one passed into the function). You try to check each one to see if it's exactly "." (except you don't, because you're using == instead of isEqualToString), and if it is then you replace that entire string by what ever the user's just typed. Very odd indeed!
Based on your description of what yo want to do, how about:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *decmial = #".";
if ([string isEqualToString:decmial])
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:decmial withString:#""];
if (textField == octet1) {
[octet2 becomeFirstResponder];
}
else if (textField == octet2) {
[octet3 becomeFirstResponder];
}
else if (textField == octet3) {
[octet4 becomeFirstResponder];
}
else if (textField == octet4) {
[myBitMask becomeFirstResponder];
}
// We've done the replacement ourselves and moved to the next field. Don't allow the system to accept the change
return NO;
}
// Default behavior
return YES;
}

Resources