I am using this code to check if a user input string contains only alpha-numeric chars in iOS6:
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet];
NSString *trimmedString = [text stringByTrimmingCharactersInSet:alphaSet];
BOOL valid = [trimmedString isEqualToString:#""];
but here's the result of running this piece of code:
Note that the text (string to be checked) contains only Chinese chars, but after trim by alphaSet it becomes an empty string and passed the verification.
I also tried this code and it is also not working:
- (BOOL) isAlphaNumeric: (NSString *) text
{
NSCharacterSet *unwantedCharacters =
[[NSCharacterSet alphanumericCharacterSet] invertedSet];
return ([text rangeOfCharacterFromSet:unwantedCharacters].location == NSNotFound) ? YES : NO;
}
I am not sure where I am doing wrong. Do I need to encode the input text somehow before I do the check?
Currently I get the string directly from iOS6's - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text's last replacementText parameter.
Thanks!
The problem is that alphanumericCharacterSet also seems to contain the chinese letters, so the result is "correct". Apple doesn't document it this way but I've seen a few postings (e.g. from GNUStep) that seem to indicate it. (Also note that Apple does document that this set contains characters that you might not want: Informally, this set is the set of all characters used as basic units of alphabets, syllabaries, ideographs, and digits.).
A simple yet inelegant workaround is to define the character set yourself, if all you want is the english alphabet without any foreign letters like Ü or ß:
NSCharacterSet *alphaSet = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890"];
When you're targeting iOS >= 7, one of the URL*AllowedCharacterSet might be of interest. See the NSCharacterSet documentation for details.
Related
I have a text field which the user enters a number and it gets converted to an integer.
The keyboard set is to decimal numerical one. Except the paste function is still enabled so the user can paste text into it.
I want to set it to change a label to #"error" if the user enters a non numerical value into it.
I do not want to disable the paste function as I still want the user to have the ability to copy and paste their own numerical values into my app.
Simply disallowing entry of non-numeric characters is one way. But what you asked is how do you detect non-numerics...
Use
NSRange range = [myTextField.text rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
if(range.location == NSNotFound) {
// then it is numeric only
}
If you want apply restriction that use have to only enter numeric value then use delegate method of UITextField:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0) || [string isEqualToString:#""];
}
This will returns YES if the string is numeric, otherwise return NO.
EDITE:
#Adam's answer is the best for check text is only numeric or not.
NSRange range = [myTextField.text rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
I am trying to restrict the user to enter max 50 words in UITextView. I tried solution by PengOne from this question1 . This works for me except user can enter unlimited chars in the last word.
So I thought of using regular expression. I am using the regular expression given by
VonC in this question2. But this does not allow me enter special symbols like , " # in the text view.
In my app , user can enter anything in the UITextView or just copy-paste from web page , notes , email etc.
Can anybody know any alternate solution for this ?
Thanks in advance.
This code should work for you.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
return textView.text.length + (text.length - range.length) <= 50;
}
Do as suggested in "question2", but add # within the brackets so that you can enter that as well. May need to escape it if anything treats it as a special character.
You use [NSCharacterSet whitespaceCharacterSet] to calculate word.
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
static const NSUInteger MAX_NUMBER_OF_LINES_ALLOWED = 3;
NSMutableString *t = [NSMutableString stringWithString: self.textView.text];
[t replaceCharactersInRange: range withString: text];
NSUInteger numberOfLines = 0;
for (NSUInteger i = 0; i < t.length; i++) {
if ([[NSCharacterSet whitespaceCharacterSet] characterIsMember: [t characterAtIndex: i]]) {
numberOfWord++;
}
}
return (numberOfWord < 50);
}
The method textViewDidChangeSelection: is called when a section of text is selected or the selection is changed, such as when copying or pasting a section of text.
I have a table row which has some data entry by using UITextField.
Lets say I have some data in it "my data"
Next time when I come back to this activity, I want to edit it and append with . using double space keyboard shortcut to get the result as "my data."
The issue is when I use double space shortvut it overwrite it and replace the value of UITextfield with ". "
Is there any way to append this shortcut.
I hope I explain my problem correctly.
Well after lot of digging and some manipulation I have following answer, this could help if some one has the same issue.
use following delegate call
(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
and copy the following code to fix the issue described above.
//Check for double space, hot key shortcut provided on keyboard.
if((range.location > 0 &&
[string length] > 0 &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[string characterAtIndex:0]] &&
[[NSCharacterSet whitespaceCharacterSet] characterIsMember:[[textField text] characterAtIndex:range.location - 1]])) {
//Manually replace the space with your own space, programmatically
NSRange backward = NSMakeRange(range.location - 1, 1);
textField.text = [rightTextField.text stringByReplacingCharactersInRange:backward withString:#". "];
return NO;
}
This will append . to the existing data in UITextField.
Still looking for better answer.
Thanks to the help of those on SO, I have a great UISearchBar that filters my UITableView. There is one more feature that I'd like to add.
I would like the UISearchBar filter to ignore special characters like apostrophes, commas, dashes, etc... and to allow cells with text like "Jim's Event" or "Jims-Event" to still come up if the user types "Jims Event".
for (NSDictionary *item in listItems)
{
if ([scope isEqualToString:#"All"] || [[item objectForKey:#"type"]
isEqualToString:scope] || scope == nil)
{
NSStringCompareOptions opts = (NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch);
NSRange resultRange = [[item objectForKey:#"name"] rangeOfString:searchText
options:opts];
if (resultRange.location != NSNotFound) {
[filteredListItems addObject:item];
}
}
}
Anyone have any ideas? Thank you!
This one is a little tricky. The first solution that comes to mind is to strip any character that you deliberately don't want to match from both the search and item strings, then do the comparison. You can use NSCharacterSet instances to do that filtering:
// Use this method to filter all instances of unwanted characters from `str`
- (NSString *)string:(NSString *)str filteringCharactersInSet:(NSCharacterSet *)set {
return [[str componentsSeparatedByCharactersInSet:set]
componentsJoinedByString:#""];
}
// Then, in your search function....
NSCharacterSet *unwantedCharacters = [[NSCharacterSet alphanumericCharacterSet]
invertedSet];
NSString *strippedItemName = [self string:[item objectForKey:#"name"]
filteringCharactersInSet:unwantedCharacters];
NSString *strippedSearch = [self string:searchText
filteringCharactersInSet:unwantedCharacters];
Once you have the stripped strings, you can do your search, using strippedItemName in place of [item objectForKey:#"name"] and strippedSearch in place of searchText.
In your example, this would:
Translate the search string "Jims Event" to "JimsEvent" (stripping the space)
Translate an item "Jim's Event" to "JimsEvent" (stripping the apostrophe and space)
Match the two, since they're the same string
You might consider stripping your search text of unwanted characters once, before you loop over item names, rather than redoing the same work every iteration of your loop. You can also filter more or fewer characters by using a set other than alphanumericCharacterSet - take a look at the class reference for more.
Edit: we need to use a custom function to get rid of all characters in the given set. Just using -[NSString stringByTrimmingCharactersInSet:] only filters from the ends of the string, not anywhere in the string. We get around that by splitting the original string on the unwanted characters (dropping them in the process), then rejoining the components with an empty string.
I've created a custom keyboard with my own Unicode characters... The app works great but when I press the back space it will sometimes not backspace and other times it will.. and often after I've gotten it to delete the previous character with my backspace the other letters buttons will no longer type the unicode characters I want...
Here is one of my Unicode characters code:
textViewString = [[NSString alloc] initWithFormat:#"%#%#", textView.text, char6String];
[textView setText:textViewString];
Where "char6string" would just be one of my unicode characters in this case "π"
Here is the backspace buttons code:
if ([textView.text length]>0) {
textView.text = [textView.text substringToIndex:([textView.text length]-1)];
}
I'm doing something similar in one of my apps and haven't seen any issues by using setText: rather than textView.text =.
NSUInteger length = [self.textField.text length];
if (length>0) {
[self.textField setText:[text substringToIndex:length-1]];
}
Hope this helps!
Well, I figured out the problem and it's a messy solution.. for whatever reason when you trio to add any of the new unicode characters that came out about 4 months ago to a text field via code it adds that unicode character along with a weird glitches unicode character that doesn't exist resulting in uncopyable text and 2 characters added... so now I need to detect if when a button was pressed to add a character if it changes the length by 1 or 2 and if it changes the length by 2 it's a new unicode character and I need to do an auto-delete then and there, otherwise if it only increases by one it's fine and I don't need to do anything!
My new add character to textView string looks like this for each button:
length1 = [textView.text length];
textView.text = [textView.text stringByAppendingString:char1String];
length2 = [textView.text length];
if (((length2)-(2))==length1) {
[textView setText:[textView.text substringToIndex:length2-1]];
}