Objective-C: Numbers only text field? [duplicate] - objective-c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Iphone UITextField only integer
I want to place a text field that only accepts numbers (0-9, doesn't even need decimals), but even using the "Number Pad" entry option I still get a keyboard with various symbols on it. Is there a better control for this, is there a better control for what I'm doing, or do I just have to validate input manually?

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
/* for backspace */
if([string length]==0){
return YES;
}
/* limit to only numeric characters */
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if ([myCharSet characterIsMember:c]) {
return YES;
}
}
return NO;
}

The code is somehow incorrect, should be
/* limit to only numeric characters */
NSCharacterSet* numberCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; ++i)
{
unichar c = [string characterAtIndex:i];
if (![numberCharSet characterIsMember:c])
{
return NO;
}
}
return YES;

The following code will allow you to only input numbers as well as limit the amount of characters that can be used.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
/* limit to only numeric characters */
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if ([myCharSet characterIsMember:c]) {
return YES;
}
}
/* limit the users input to only 9 characters */
NSUInteger newLength = [customTextField.text length] + [string length] - range.length;
return (newLength > 9) ? NO : YES;
}

Related

Restricting NSTextField input to alpha-numeric

I'm making a simple app in which there is an NSTextField and I want only alpha-numeric characters in it while typing.
Can anyone suggest an approach to this please?
There's a built-in support for that.
In Interface Builder check "Only Roman Characters" option for the text field.
OR
In your code set this property:
[myTextField.cell setAllowedInputSourceLocales: #[NSAllRomanInputSourcesLocaleIdentifier]];
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([self validCharecter:textField.text){
return YES;
}
else{
return NO:
}
}
-(BOOL)validCharecter :(NSString)textStr{
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet];
BOOL validStr = [[textStr stringByTrimmingCharactersInSet:alphaSet] isEqualToString:#""];
return validStr;
}
Try with dis hope it will helps you!!
Take a look at below code sample.
I hope this will help you.
//#define CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
//#define CHARACTERS_NUMBERS [CHARACTERS stringByAppendingString:#"1234567890"]
///// Inside shouldChangeCharactersInRange
///////////>>>>>>>>>>>>>>>>>>
if(textField== txtFldAlpha)
{
//Alpha only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *unacceptedInput =
[[NSCharacterSet characterSetWithCharactersInString:CHARACTERS] invertedSet];
// Create array of strings from incoming string using the unacceptable
// characters as the trigger of where to split the string.
// If array has more than one entry, there was at least one unacceptable character
if ([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] > 1)
return NO;
else
return YES&&(newLength < 26);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFldNumeric)
{
//Num only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([[string componentsSeparatedByCharactersInSet:nonNumberSet] count] > 1)
return NO;
else
return YES&&(newLength < 6);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFieldNumAlphaSpecial)
{
//Num,Alpha,Special field
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 50) ? NO : YES;
}
///////////<<<<<<<<<<<<<<<<<<
#define ACCEPTABLE_CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [string isEqualToString:filtered];
}
OR
Implement
textField:shouldChangeCharactersInRange:replacementString:
in the delegate, check the replacement string for special characters, and disallow the replacement if you detect any.
The easiest way to check for non-alphanumerics is as follows:
if ([replacementString rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
// There are non-alphanumeric characters in the replacement string
}
Hope this helps mate .. !

compare characters from nsstring to different charactersets

I want to compare each character in an nsstring one by one to different nscharactersets and perform different operations according to the characterset it matches.
I'm able to assign each character to a substring for comparison using a for loop.
- (void) compareCharactersOfWord: (NSString *) word {
for (int i = 0; i<[word length]; i++) {
NSString *substring = [word substringWithRange:NSMakeRange(i,1)];
//need to compare the substring to characterset here
}
}
I also have my two charactersets
setOne = [[NSCharacterSet characterSetWithCharactersInString:#"EAIONRTLSU"]invertedSet];
setTwo = [[NSCharacterSet characterSetWithCharactersInString:#"DG"] invertedSet];
I'm a bit lost on the comparison part. I tried different methods like "rangeOfCharacterFromSet" but I kept getting erros. in pseudocode I would need something like
if (setOne containsCharacterFrom substring) {
//do stuff here
} else if (setTwo containsCharacterFrom substring) {
//do other stuff here
}
To see if your 'substring' variable in one of your sets you would do:
if ([substring rangeOfCharacterFromSet:setOne].location != NSNotFound) {
// substring is in setOne
} else if ([substring rangeOfCharacterFromSet:setTwo].location != NSNotFound) {
// substring is in setTwo
}
Another option is to work with characters.
for (int i = 0; i<[word length]; i++) {
unichar ch = [word characterAtIndex:i];
if ([setOne characterIsMember:ch]) {
// in setOne
} else if ([setTwo characterIsMember:ch]) {
// in setTwo
}
}
There one big limitation to the second option. It doesn't work with Unicode characters higher than 0xFFFF.
You need to extract each character (unichar) from the string and use [NSCharacterSet characterIsMember:] to determine if it's part of either NSCharacterSet:
- (void) compareCharactersOfWord: (NSString *)word
{
// These could be initialised globally to speed things up a little...
NSCharacterSet *setOne = [[NSCharacterSet characterSetWithCharactersInString:#"EAIONRTLSU"] invertedSet];
NSCharacterSet *setTwo = [[NSCharacterSet characterSetWithCharactersInString:#"DG"] invertedSet];
for (NSUInteger index = 0; index < [word length]; index++)
{
unichar c = [word characterAtIndex:index];
if ([setOne characterIsMember:c])
{
// c is a member of character set #1
}
else if ([setTwo characterIsMember:c])
{
// c is a member of character set #2
}
else
{
// c is a member of neither character set
}
}
}

Restrict user to only entering one word in UITextField

Is there a way to only allow the user enter one word in the UITextField? If so, how?
Here's the current code that I'm using:
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
_disallowedCharacters = [NSCharacterSet whitespaceCharacterSet];
for(int i = 0; i < [_searchBox.text length]; i++){
unichar c = [_searchBox.text characterAtIndex:i];
if (![_disallowedCharacters characterIsMember:c])
{
return NO;
}
}
return YES;
}
Use the UITextFieldDelegate protocol:
- (BOOL) textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)textEntered
{
for (int i = 0; i < [textEntered length]; i++)
{
unichar c = [textEntered characterAtIndex:i];
if ([disallowedCharacters characterIsMember:c])
{
return NO;
}
}
return YES;
}
where disallowedCharacters is an NSCharacterSet containing the characters that should not be accepted by the keyboard, i.e. a space, punctuation, numbers, etc:
self.disallowedCharacters = [NSCharacterSet characterSetWithCharactersInString:#" ,.123"];
For a character set (for Evan's answer) that checks against whitespace and newlines, you can use
self.disallowedCharacters = [NSCharacterSet whitespaceAndNewlineCharacterSet];
If you want to check against characters besides whitespace and newlines, create a mutableCopy and add whatever you'd like to it:
NSMutableCharacterSet *set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
[set formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
[set formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet];
[set addCharactersInString:#"whatever you want"];
...
self.disallowedCharacters = [[set copy] autorelease];
[set release];
The NSCharacterSet docs have a good overview of the character sets available to you.

Remove only first instance of a character from a list of characters

Here's what I want to do. I have 2 strings and I want to determine if one string is a permutation of another. I was thinking to simply remove the characters from string A from string B to determine if any characters are left. If no, then it passes.
However, I need to make sure that only 1 instance of each letter is removed (not all occurrences) unless there are multiple letters in the word.
An example:
String A: cant
String B: connect
Result: -o-nec-
Experimenting with NSString and NSScanner has yielded no results so far.
Hmmm, let's have a go:
NSString *stringA = #"cant";
NSString *stringB = #"connect";
NSUInteger length = [stringB length];
NSMutableCharacterSet *charsToRemove = [NSMutableCharacterSet characterSetWithCharactersInString:stringA];
unichar *buffer = calloc(length, sizeof(unichar));
[stringB getCharacters:buffer range:NSMakeRange(0, length)];
for (NSUInteger i = 0; i < length; i++)
{
if ([charsToRemove characterIsMember:buffer[i]])
{
[charsToRemove removeCharactersInRange:NSMakeRange(buffer[i], 1)];
buffer[i] = '-';
}
}
NSString *result = [NSString stringWithCharacters:buffer length:length];
free (buffer);
An inefficient yet simple way might be something like this (this is implemented as a category on NSString, but it could just as easily be a method or function taking two strings):
#implementation NSString(permutation)
- (BOOL)isPermutation:(NSString*)other
{
if( [self length] != [other length] ) return NO;
if( [self isEqualToString:other] ) return YES;
NSUInteger length = [self length];
NSCountedSet* set1 = [[[NSCountedSet alloc] initWithCapacity:length] autorelease];
NSCountedSet* set2 = [[[NSCountedSet alloc] initWithCapacity:length] autorelease];
for( int i = 0; i < length; i++ ) {
NSRange range = NSMakeRange(i, 1);
[set1 addObject:[self substringWithRange:range]];
[set2 addObject:[self substringWithRange:range]];
}
return [set1 isEqualTo:set2];
}
#end
This returns what your example asks for...
NSString* a = #"cant";
NSString* b = #"connect";
NSMutableString* mb = [NSMutableString stringWithString:b];
NSUInteger i;
for (i=0; i<[a length]; i++) {
NSString* theLetter = [a substringWithRange:NSMakeRange(i, 1)];
NSRange r = [mb rangeOfString:theLetter];
if (r.location != NSNotFound) {
[mb replaceCharactersInRange:r withString:#"-"];
}
}
NSLog(#"mb: %#", mb);
However, I wouldn't call that a permutation. To me a permutation would only hold true if all the characters from string "a" were contained by string "b". In your example, since the letter a in cant isn't in string b then I would say that cant is not a permutation of connect. With this definition I would use this:
-(BOOL)isString:(NSString*)firstString aPermutationOfString:(NSString*)secondString {
BOOL isPermutation = YES;
NSMutableString* mb = [NSMutableString stringWithString:secondString];
NSUInteger i;
for (i=0; i<[firstString length]; i++) {
NSString* theLetter = [firstString substringWithRange:NSMakeRange(i, 1)];
NSRange r = [mb rangeOfString:theLetter];
if (r.location != NSNotFound) {
[mb deleteCharactersInRange:r];
} else {
return NO;
}
}
return isPermutation;
}

Number of occurrences of a substring in an NSString?

How can I get the number of times an NSString (for example, #"cake") appears in a larger NSString (for example, #"Cheesecake, apple cake, and cherry pie")?
I need to do this on a lot of strings, so whatever method I use would need to be relatively fast.
Thanks!
This isn't tested, but should be a good start.
NSUInteger count = 0, length = [str length];
NSRange range = NSMakeRange(0, length);
while(range.location != NSNotFound)
{
range = [str rangeOfString: #"cake" options:0 range:range];
if(range.location != NSNotFound)
{
range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
count++;
}
}
A regex like the one below should do the job without a loop interaction...
Edited
NSString *string = #"Lots of cakes, with a piece of cake.";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"cake" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
NSLog(#"Found %i",numberOfMatches);
Only available on iOS 4.x and superiors.
was searching for a better method then mine but here's another example:
NSString *find = #"cake";
NSString *text = #"Cheesecake, apple cake, and cherry pie";
NSInteger strCount = [text length] - [[text stringByReplacingOccurrencesOfString:find withString:#""] length];
strCount /= [find length];
I would like to know which one is more effective.
And I made an NSString category for better usage:
// NSString+CountString.m
#interface NSString (CountString)
- (NSInteger)countOccurencesOfString:(NSString*)searchString;
#end
#implementation NSString (CountString)
- (NSInteger)countOccurencesOfString:(NSString*)searchString {
NSInteger strCount = [self length] - [[self stringByReplacingOccurrencesOfString:searchString withString:#""] length];
return strCount / [searchString length];
}
#end
simply call it by:
[text countOccurencesOfString:find];
Optional:
you can modify it to search case insensitive by defining options:
There are a couple ways you could do it. You could iteratively call rangeOfString:options:range:, or you could do something like:
NSArray * portions = [aString componentsSeparatedByString:#"cake"];
NSUInteger cakeCount = [portions count] - 1;
EDIT I was thinking about this question again and I wrote a linear-time algorithm to do the searching (linear to the length of the haystack string):
+ (NSUInteger) numberOfOccurrencesOfString:(NSString *)needle inString:(NSString *)haystack {
const char * rawNeedle = [needle UTF8String];
NSUInteger needleLength = strlen(rawNeedle);
const char * rawHaystack = [haystack UTF8String];
NSUInteger haystackLength = strlen(rawHaystack);
NSUInteger needleCount = 0;
NSUInteger needleIndex = 0;
for (NSUInteger index = 0; index < haystackLength; ++index) {
const char thisCharacter = rawHaystack[index];
if (thisCharacter != rawNeedle[needleIndex]) {
needleIndex = 0; //they don't match; reset the needle index
}
//resetting the needle might be the beginning of another match
if (thisCharacter == rawNeedle[needleIndex]) {
needleIndex++; //char match
if (needleIndex >= needleLength) {
needleCount++; //we completed finding the needle
needleIndex = 0;
}
}
}
return needleCount;
}
A quicker to type, but probably less efficient solution.
- (int)numberOfOccurencesOfSubstring:(NSString *)substring inString:(NSString*)string
{
NSArray *components = [string componentsSeparatedByString:substring];
return components.count-1; // Two substring will create 3 separated strings in the array.
}
Here is a version done as an extension to NSString (same idea as Matthew Flaschen's answer):
#interface NSString (my_substr_search)
- (unsigned) countOccurencesOf: (NSString *)subString;
#end
#implementation NSString (my_substring_search)
- (unsigned) countOccurencesOf: (NSString *)subString {
unsigned count = 0;
unsigned myLength = [self length];
NSRange uncheckedRange = NSMakeRange(0, myLength);
for(;;) {
NSRange foundAtRange = [self rangeOfString:subString
options:0
range:uncheckedRange];
if (foundAtRange.location == NSNotFound) return count;
unsigned newLocation = NSMaxRange(foundAtRange);
uncheckedRange = NSMakeRange(newLocation, myLength-newLocation);
count++;
}
}
#end
<somewhere> {
NSString *haystack = #"Cheesecake, apple cake, and cherry pie";
NSString *needle = #"cake";
unsigned count = [haystack countOccurencesOf: needle];
NSLog(#"found %u time%#", count, count == 1 ? #"" : #"s");
}
If you want to count words, not just substrings, then use CFStringTokenizer.
Here's another version as a category on NSString:
-(NSUInteger) countOccurrencesOfSubstring:(NSString *) substring {
if ([self length] == 0 || [substring length] == 0)
return 0;
NSInteger result = -1;
NSRange range = NSMakeRange(0, 0);
do {
++result;
range = NSMakeRange(range.location + range.length,
self.length - (range.location + range.length));
range = [self rangeOfString:substring options:0 range:range];
} while (range.location != NSNotFound);
return result;
}
Swift solution would be:
var numberOfSubstringAppearance = 0
let length = count(text)
var range: Range? = Range(start: text.startIndex, end: advance(text.startIndex, length))
while range != nil {
range = text.rangeOfString(substring, options: NSStringCompareOptions.allZeros, range: range, locale: nil)
if let rangeUnwrapped = range {
let remainingLength = length - distance(text.startIndex, rangeUnwrapped.endIndex)
range = Range(start: rangeUnwrapped.endIndex, end: advance(rangeUnwrapped.endIndex, remainingLength))
numberOfSubstringAppearance++
}
}
Matthew Flaschen's answer was a good start for me. Here is what I ended up using in the form of a method. I took a slightly different approach to the loop. This has been tested with empty strings passed to stringToCount and text and with the stringToCount occurring as the first and/or last characters in text.
I use this method regularly to count paragraphs in the passed text (ie. stringToCount = #"\r").
Hope this of use to someone.
- (int)countString:(NSString *)stringToCount inText:(NSString *)text{
int foundCount=0;
NSRange range = NSMakeRange(0, text.length);
range = [text rangeOfString:stringToCount options:NSCaseInsensitiveSearch range:range locale:nil];
while (range.location != NSNotFound) {
foundCount++;
range = NSMakeRange(range.location+range.length, text.length-(range.location+range.length));
range = [text rangeOfString:stringToCount options:NSCaseInsensitiveSearch range:range locale:nil];
}
return foundCount;
}
Example call assuming the method is in a class named myHelperClass...
int foundCount = [myHelperClass countString:#"n" inText:#"Now is the time for all good men to come to the aid of their country"];
for(int i =0;i<htmlsource1.length-search.length;i++){
range = NSMakeRange(i,search.length);
checker = [htmlsource1 substringWithRange:range];
if ([search isEqualToString:checker]) {
count++;
}
}
No built-in method. I'd suggest returning a c-string and using a common c-string style algorithm for substring counting... if you really need this to be fast.
If you want to stay in Objective C, this link might help. It describes the basic substring search for NSString. If you work with the ranges, adjust and count, then you'll have a "pure" Objective C solution... albeit, slow.
-(IBAction)search:(id)sender{
int maincount = 0;
for (int i=0; i<[self.txtfmainStr.text length]; i++) {
char c =[self.substr.text characterAtIndex:0];
char cMain =[self.txtfmainStr.text characterAtIndex:i];
if (c == cMain) {
int k=i;
int count=0;
for (int j = 0; j<[self.substr.text length]; j++) {
if (k ==[self.txtfmainStr.text length]) {
break;
}
if ([self.txtfmainStr.text characterAtIndex:k]==[self.substr.text characterAtIndex:j]) {
count++;
}
if (count==[self.substr.text length]) {
maincount++;
}
k++;
}
}
NSLog(#"%d",maincount);
}
}