Password validation in UITextField in iOS 10 --> Objective C - ios

I'm having 1 UITextfield for password in my iPhone application.
I want to validate this textfield with the following validation.
Must be at least 6 characters
Must contain at least one english letter, one digit and Remaining all
special characters are make as optional (ie not mandetory)
how can I restrict the UITextField with above requirements. please anyone help me out to do this..

Use this method to validate your password:
-(BOOL) isPasswordValid:(NSString *)password {
NSCharacterSet *upperCaseChars = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLKMNOPQRSTUVWXYZ"];
NSCharacterSet *lowerCaseChars = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyz"];
//NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
if ( [password length]<7 )
return NO; //too short
NSRange range;
range = [password rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
if ( !range.length )
return NO; // no letter
range = [password rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
if ( !range.length )
return NO; // no number;
range = [password rangeOfCharacterFromSet:upperCaseChars];
if ( !range.length )
return NO; // no uppercase letter;
range = [password rangeOfCharacterFromSet:lowerCaseChars];
if ( !range.length )
return NO; // no lowerCase Chars;
return YES;
}

Below is what I use using RegEx
NSString *passwordRegex = #"^.*(?=.{6,})(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##$!&]).*$";
NSPredicate *passwordTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", passwordRegex];
if (![passwordTest evaluateWithObject:passwordTF.text]) {
// Password must be at least 6 character, containing lowercase letter, one uppercase letter, digits, and special character (!##$&)
}

Try this :
-(BOOL)isValidPasswordWithText:(UITextField *)textfield{
NSString *regex1 = #"^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d$#$!%*#?&]{6,}$";
NSPredicate *test1 = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex1];
return [test1 evaluateWithObject:textfield.text] ;
}

Inspired by Vamshi Krishna's answer, I think it could be more simple.
The decimalDigitCharacterSet can match any digital characters. Since the OP's intention didn't mention the upper case issue, so the letterCharacterSet should be enough here.
FYI:
BOOL ValidatePassword(NSString *candidate)
{
if (candidate.length < 6) {
return NO;
}
BOOL foundLetter = [candidate rangeOfCharacterFromSet:NSCharacterSet.letterCharacterSet].location != NSNotFound;
BOOL foundDigit = [candidate rangeOfCharacterFromSet:NSCharacterSet.decimalDigitCharacterSet].location != NSNotFound;
return foundLetter && foundDigit;
}

Related

How to validate a password which must contain either number or alphabets(or both) as well as special characters?

hi am currently using the following to validate the password but i want to include special characters also. Currently it contains only numbers and alphabets. Please help.
- (BOOL)validatePassword:(NSString *) password{
NSString *ACCEPTABLE_CHARECTERS = #"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARECTERS] invertedSet];
NSString *filtered = [[password componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [password isEqualToString:filtered];
}
You can try this
- (BOOL)validatePassword:(NSString *) password{
if(password.length == 0){
return NO;
}
NSString *regex = #"^(?=(.*\d){2})(?=.*[a-zA-Z])(?=.*[!##$%])[0-9a-zA-Z!##$%]{8,}";
NSPredicate *passwordPredicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
return [passwordPredicate evaluateWithObject:password];
}
EXPLANATION
(?=(.*\d){2}) - uses lookahead (?=) and says the password must contain at least 2 digits
(?=.*[a-zA-Z]) - uses lookahead and says the password must contain an alpha
(?=.*[!##$%]) - uses lookahead and says the password must contain 1 or more special characters which are defined
[0-9a-zA-Z!##$%] - dictates the allowed characters
{8,} - says the password must be at least 8 characters long
It might need a little tweaking e.g. specifying exactly which special characters you need but it should do the trick.
-(BOOL)validatePassword:(NSString *) password{
NSString *COMMON_CHARECTERS = #"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
NSString *SPECIAL_CHARECTERS = #"##$%^&*";
NSCharacterSet *cs_common = [NSCharacterSet characterSetWithCharactersInString:COMMON_CHARECTERS];
NSCharacterSet *cs_special = [NSCharacterSet characterSetWithCharactersInString:SPECIAL_CHARECTERS];
NSString *filtere_common = [[password componentsSeparatedByCharactersInSet:cs_common] componentsJoinedByString:#""];
NSString *filtere_special = [[password componentsSeparatedByCharactersInSet:cs_special] componentsJoinedByString:#""];
BOOL valid = (password.length == (filtere_common.length + filtere_special.length));
return valid;
}
You can use regex to identify use of special character. like
^([a-zA-Z+]+[0-9+]+[&#!#+]+)$
You can use character sets as well to validate password:- Check this link

How to get the first alphabet character of a string in iOS

I have an example NSString in iOS
NSString* str = #"-- This is an example string";
I want to get the first alphabet letter. The result of above situation is letter "T" from word "This". Some characters before letter "T" is not alphabet letter so it returns the first alphabet letter is "T".
How can I retrieve it? If the string not contain any alphabet letter, it can return nil.
Besides, the result can be a NSRange
NSRange range = [string rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
First create a NSCharecterSet as a global variable and write this code
-(void)viewDidLoad{
NSCharacterSet *s = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
s = [s invertedSet];
NSString *myString = #"--- This is a string";
NSArray *arrayOfStrings = [myString componentsSeparatedByString:#" "];
for(int i=0;i<arrayOfStrings.count){
NSString *current = [arrayOfStrings objectAtIndex:i];
char c = [self returnCharacter:current];
if(c == nil){
//that means first word is not with alphabets;
}
else {
NSLog(#"%c",c);
//your output.
}
}
}
And here is the method
-(char)returnChracter:(NSString*)string{
NSRange r = [string rangeOfCharacterFromSet:s];
if (r.location != NSNotFound) {
NSLog(#"the string contains illegal characters");
return nil;
}
else {
//string contains all alphabets
char firstLetter = [string charAtIndex:0];
return firstLetter;
}
}
You can use the following function. Pass a string and get first character as a string.
-(NSString*)getFirstCharacter:(NSString*)string
{
for(int i=0;i<string.length;i++)
{
unichar firstChar = [string characterAtIndex:i];
NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
if ([letters characterIsMember:firstChar]) {
return [NSString:stringWithFormat:#"%c",firstChar];
}
}
return nil;
}

RegEx validation of techmahindra account

I want to validate for textfield of email and wants to find out is it techmahindra email or not. How can I find it . I am attaching my code here.
Could any one suggest changes.
NSString * myString = # "#";
NSArray * myWords = [emailStr componentsSeparatedByString: myString];
NSString * str = [myWords objectAtIndex: 1];
if ([str isEqualToString: # "techmahindra.com"]) {
NSString * emailRegex = # "[A-Z0-9a-z._%+]+#[A-Za-z0-9.]+\\.[A-Za-z]{2,4}";
NSPredicate * emailTest = [NSPredicate predicateWithFormat: # "SELF MATCHES %#", emailRegex];
return [emailTest evaluateWithObject: emailStr];
} else
return NO;
Given that you have written code to extract the part of the string that follows the # symbol, you don't need regular expressions there. You can simply do a case-insensitive comparison, like this:
if (str != nil && [str compare:#"techmahindra.com" options:NSCaseInsensitiveSearch]) {
return [emailTest evaluateWithObject:emailStr];
}
else
return NO;
You probably should also trim whitespace as part of your email validation code as this check will fail if there is a trailing space for example.

Getting just the phone number digits from kABPersonPhoneProperty in iOS [duplicate]

I have an NSString (phone number) with some parenthesis and hyphens as some phone numbers are formatted. How would I remove all characters except numbers from the string?
Old question, but how about:
NSString *newString = [[origString componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""];
It explodes the source string on the set of non-digits, then reassembles them using an empty string separator. Not as efficient as picking through characters, but much more compact in code.
There's no need to use a regular expressions library as the other answers suggest -- the class you're after is called NSScanner. It's used as follows:
NSString *originalString = #"(123) 123123 abc";
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:originalString.length];
NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
NSLog(#"%#", strippedString); // "123123123"
EDIT: I've updated the code because the original was written off the top of my head and I figured it would be enough to point the people in the right direction. It seems that people are after code they can just copy-paste straight into their application.
I also agree that Michael Pelz-Sherman's solution is more appropriate than using NSScanner, so you might want to take a look at that.
The accepted answer is overkill for what is being asked. This is much simpler:
NSString *pureNumbers = [[phoneNumberString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:#""];
This is great, but the code does not work for me on the iPhone 3.0 SDK.
If I define strippedString as you show here, I get a BAD ACCESS error when trying to print it after the scanCharactersFromSet:intoString call.
If I do it like so:
NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];
I end up with an empty string, but the code doesn't crash.
I had to resort to good old C instead:
for (int i=0; i<[phoneNumber length]; i++) {
if (isdigit([phoneNumber characterAtIndex:i])) {
[strippedString appendFormat:#"%c",[phoneNumber characterAtIndex:i]];
}
}
Though this is an old question with working answers, I missed international format support. Based on the solution of simonobo, the altered character set includes a plus sign "+". International phone numbers are supported by this amendment as well.
NSString *condensedPhoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:
[[NSCharacterSet characterSetWithCharactersInString:#"+0123456789"]
invertedSet]]
componentsJoinedByString:#""];
The Swift expressions are
var phoneNumber = " +1 (234) 567-1000 "
var allowedCharactersSet = NSMutableCharacterSet.decimalDigitCharacterSet()
allowedCharactersSet.addCharactersInString("+")
var condensedPhoneNumber = phoneNumber.componentsSeparatedByCharactersInSet(allowedCharactersSet.invertedSet).joinWithSeparator("")
Which yields +12345671000 as a common international phone number format.
Here is the Swift version of this.
import UIKit
import Foundation
var phoneNumber = " 1 (888) 555-5551 "
var strippedPhoneNumber = "".join(phoneNumber.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
Swift version of the most popular answer:
var newString = join("", oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
Edit: Syntax for Swift 2
let newString = oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
Edit: Syntax for Swift 3
let newString = oldString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
Thanks for the example. It has only one thing missing the increment of the scanLocation in case one of the characters in originalString is not found inside the numbers CharacterSet object. I have added an else {} statement to fix this.
NSString *originalString = #"(123) 123123 abc";
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:originalString.length];
NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[strippedString appendString:buffer];
}
// --------- Add the following to get out of endless loop
else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
// --------- End of addition
}
NSLog(#"%#", strippedString); // "123123123"
It Accept only mobile number
NSString * strippedNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"[^0-9]" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, [mobileNumber length])];
It might be worth noting that the accepted componentsSeparatedByCharactersInSet: and componentsJoinedByString:-based answer is not a memory-efficient solution. It allocates memory for the character set, for an array and for a new string. Even if these are only temporary allocations, processing lots of strings this way can quickly fill the memory.
A memory friendlier approach would be to operate on a mutable copy of the string in place. In a category over NSString:
-(NSString *)stringWithNonDigitsRemoved {
static NSCharacterSet *decimalDigits;
if (!decimalDigits) {
decimalDigits = [NSCharacterSet decimalDigitCharacterSet];
}
NSMutableString *stringWithNonDigitsRemoved = [self mutableCopy];
for (CFIndex index = 0; index < stringWithNonDigitsRemoved.length; ++index) {
unichar c = [stringWithNonDigitsRemoved characterAtIndex: index];
if (![decimalDigits characterIsMember: c]) {
[stringWithNonDigitsRemoved deleteCharactersInRange: NSMakeRange(index, 1)];
index -= 1;
}
}
return [stringWithNonDigitsRemoved copy];
}
Profiling the two approaches have shown this using about 2/3 less memory.
You can use regular expression on mutable string:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:
#"[^\\d]"
options:0
error:nil];
[regex replaceMatchesInString:str
options:0
range:NSMakeRange(0, str.length)
withTemplate:#""];
Built the top solution as a category to help with broader problems:
Interface:
#interface NSString (easyReplace)
- (NSString *)stringByReplacingCharactersNotInSet:(NSCharacterSet *)set
with:(NSString *)string;
#end
Implemenation:
#implementation NSString (easyReplace)
- (NSString *)stringByReplacingCharactersNotInSet:(NSCharacterSet *)set
with:(NSString *)string
{
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:self.length];
NSScanner *scanner = [NSScanner scannerWithString:self];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:set intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
[strippedString appendString:string];
}
}
return [NSString stringWithString:strippedString];
}
#end
Usage:
NSString *strippedString =
[originalString stringByReplacingCharactersNotInSet:
[NSCharacterSet setWithCharactersInString:#"01234567890"
with:#""];
Swift 3
let notNumberCharacters = NSCharacterSet.decimalDigits.inverted
let intString = yourString.trimmingCharacters(in: notNumberCharacters)
swift 4.1
var str = "75003 Paris, France"
var stringWithoutDigit = (str.components(separatedBy:CharacterSet.decimalDigits)).joined(separator: "")
print(stringWithoutDigit)
Um. The first answer seems totally wrong to me. NSScanner is really meant for parsing. Unlike regex, it has you parsing the string one tiny chunk at a time. You initialize it with a string, and it maintains an index of how far along the string it's gotten; That index is always its reference point, and any commands you give it are relative to that point. You tell it, "ok, give me the next chunk of characters in this set" or "give me the integer you find in the string", and those start at the current index, and move forward until they find something that doesn't match. If the very first character already doesn't match, then the method returns NO, and the index doesn't increment.
The code in the first example is scanning "(123)456-7890" for decimal characters, which already fails from the very first character, so the call to scanCharactersFromSet:intoString: leaves the passed-in strippedString alone, and returns NO; The code totally ignores checking the return value, leaving the strippedString unassigned. Even if the first character were a digit, that code would fail, since it would only return the digits it finds up until the first dash or paren or whatever.
If you really wanted to use NSScanner, you could put something like that in a loop, and keep checking for a NO return value, and if you get that you can increment the scanLocation and scan again; and you also have to check isAtEnd, and yada yada yada. In short, wrong tool for the job. Michael's solution is better.
For those searching for phone extraction, you can extract the phone numbers from a text using NSDataDetector, for example:
NSString *userBody = #"This is a text with 30612312232 my phone";
if (userBody != nil) {
NSError *error = NULL;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber error:&error];
NSArray *matches = [detector matchesInString:userBody options:0 range:NSMakeRange(0, [userBody length])];
if (matches != nil) {
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypePhoneNumber) {
DbgLog(#"Found phone number %#", [match phoneNumber]);
}
}
}
}
`
I created a category on NSString to simplify this common operation.
NSString+AllowCharactersInSet.h
#interface NSString (AllowCharactersInSet)
- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet;
#end
NSString+AllowCharactersInSet.m
#implementation NSString (AllowCharactersInSet)
- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet {
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:self.length];
NSScanner *scanner = [NSScanner scannerWithString:self];
while (!scanner.isAtEnd) {
NSString *buffer = nil;
if ([scanner scanCharactersFromSet:characterSet intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
scanner.scanLocation = scanner.scanLocation + 1;
}
}
return strippedString;
}
#end
I think currently best way is:
phoneNumber.replacingOccurrences(of: "\\D",
with: "",
options: String.CompareOptions.regularExpression)
If you're just looking to grab the numbers from the string, you could certainly use regular expressions to parse them out. For doing regex in Objective-C, check out RegexKit. Edit: As #Nathan points out, using NSScanner is a much simpler way to parse all numbers from a string. I totally wasn't aware of that option, so props to him for suggesting it. (I don't even like using regex myself, so I prefer approaches that don't require them.)
If you want to format phone numbers for display, it's worth taking a look at NSNumberFormatter. I suggest you read through this related SO question for tips on doing so. Remember that phone numbers are formatted differently depending on location and/or locale.
Swift 5
let newString = origString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
Based on Jon Vogel's answer here it is as a Swift String extension along with some basic tests.
import Foundation
extension String {
func stringByRemovingNonNumericCharacters() -> String {
return self.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
}
}
And some tests proving at least basic functionality:
import XCTest
class StringExtensionTests: XCTestCase {
func testStringByRemovingNonNumericCharacters() {
let baseString = "123"
var testString = baseString
var newString = testString.stringByRemovingNonNumericCharacters()
XCTAssertTrue(newString == testString)
testString = "a123b"
newString = testString.stringByRemovingNonNumericCharacters()
XCTAssertTrue(newString == baseString)
testString = "a=1-2_3#b"
newString = testString.stringByRemovingNonNumericCharacters()
XCTAssertTrue(newString == baseString)
testString = "(999) 999-9999"
newString = testString.stringByRemovingNonNumericCharacters()
XCTAssertTrue(newString.characters.count == 10)
XCTAssertTrue(newString == "9999999999")
testString = "abc"
newString = testString.stringByRemovingNonNumericCharacters()
XCTAssertTrue(newString == "")
}
}
This answers the OP's question but it could be easily modified to leave in phone number related characters like ",;*#+"
NSString *originalPhoneNumber = #"(123) 123-456 abc";
NSCharacterSet *numbers = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789"] invertedSet];
NSString *trimmedPhoneNumber = [originalPhoneNumber stringByTrimmingCharactersInSet:numbers];
];
Keep it simple!

NSString is a number? [duplicate]

This question already has answers here:
Check that a input to UITextField is numeric only
(22 answers)
Closed 8 years ago.
I have a TextField and wanted to know if the user just pressed numbers
eg::
_tfNumber.text only has numbers?
is there any function on NSString for this?
This will let you know if all of the characters are numbers:
NSString *originalString = #"1234";
NSCharacterSet *numberSet = [NSCharacterSet decimalDigitCharacterSet];
NSString * trimmedString = [originalString stringByTrimmingCharactersInSet:numberSet];
if ((trimmedString.length == 0) && (originalString.length > 0)) {
NSLog(#"Original string was all numbers.");
}
Note that this ensures it won't give a false positive for the empty string, which technically also doesn't contain any non-numbers.
try this:
NSCharacterSet *_NumericOnly = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *myStringSet = [NSCharacterSet characterSetWithCharactersInString:mystring];
if ([_NumericOnly isSupersetOfSet: myStringSet]) {
NSLog(#"String has only numbers");
}
I got it from: http://i-software-developers.com/2013/07/01/check-if-nsstring-contains-only-numbers/
You can use this method in your UITextField's delegate method textField:shouldChangeCharactersInRange:replacementString: and do the verification while the user is typing.
No, but it should be easy to write:
- (BOOL)justContainsNumbers:(NSString *)str {
if ([str length] == 0)
return NO;
for (NSUInteger i = 0; i < [str length]; i++)
if (!isdigit([str characterAtIndex:i]))
return NO;
return YES;
}
Let's try regular Expression,
NSString * numberReg = #"[0-9]";
NSPredicate * numberCheck = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", numberReg];
if ([numberCheck evaluateWithObject:textField.text])
NSLog (#"Number");
No. NSString is not an NSNumber and any values you get from a UITextField will be an NSString. See THIS SO answer for converting that entered NSString value into an NSNumber.

Resources