How to dissallow certain characters in a UITextview - iphone

I have a uitextview that is editable but there are certain characters I would like to be disallowed from being typed.
How can I do that?

You can do this by assigning a delegate to the UITextView, and implementing the following method in the delegate:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
In the body just write some code that scans through the input text to see if you find the characters you want to filter, if you see them return NO, otherwise return YES.

Unfortunately, this is not that simple, because textView:shouldChangeTextInRange: replacementText: is not necessarilly called with one-character strings. It is for keyboard input, but it isn't when pasting, or when using speech recognition to enter text.
So what do you want to do if the user pastes (or dictates) a string that contains forbidden characters? You might want to let all valid text go through and only delete (or replace) unwanted characters.
The incorrect idea would be to fix the text in the textViewDidChange: delegate routine. While this seems to work, it somehow prevents speech input from working in the UITextView.
The correct idea is to implement textView:shouldChangeTextInRange: replacementText: with full filtering. Here is a sample implementation that filters out newlines:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder]; // dismiss keyboard
return NO;
}
text = [text stringByReplacingOccurrencesOfString:#"\n" withString:#" "]; // replace by spaces
NSString *fullText = [textView.text stringByReplacingCharactersInRange:range withString:text];
textView.text = fullText;
return NO;
}
Note that it dismisses the keyboard when the user strikes the enter key. But not quite perfectly: it will also dismiss the keyboard when the user pastes a single newline character. This might be a problem, but this should happen only rarely.

Related

UITextView Detect Character Removed

I created a UITextView which allows dynamic tagging when the user types #.
Is it possible to detect a # removed, in order to stop my specific tagging process that I created? If so, how can I do that? UITextView has no such delegate methods.
I would use
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
Then create an NSString in which you store the last character added to the UITextView. Within the above method, add the following snippet.
if ([text isEqualToString:#""] && [lastRecordedString isEqualToString#"#"]) {
//do whatever you want to do when an # is deleted
}
lastRecordedString = [textView.text substringFromIndex:[string length]-1];
EDIT: see the edited code above. Now lastRecordedString is the last character in the UITextView after a character is removed. This should work.
You can get the original text which will be replaced by use:
NSString *originalText = [textView.text substringWithRange:range];
in your
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
method.
Then, do
if ([originalText rangeOfString:#"tag"].length > 0) {
NSLog(#"delete tag string");
}
You will detect if user delete a specific string.
Hope that helpful!

Confirm UITextview auto-complete

This seems impossible, but maybe someone else has had the same problem.
Is it possible for me to accept an autocomplete programmatically, or in some way get the suggested word that pops up? My problem is that I'm capturing the return/backspace keystroke and then move focus to another textview. When enter/backspace is hit, the textview will ignore the auto-suggested word. It seems that it is only possible to accept an autocompletion by hit space/dot (and return for new row). With this code:
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text {
NSRange textViewRange = [textView selectedRange];
// Handle newrow and backspace.
if(([text length] == 0) && (textViewRange.location== 0) && textViewRange.length==0){
// BACKSPACE KEYSTROKE
[delegate doSomethingWhenBackspace];
return NO;
}else if ([text isEqualToString:#"\n"]){
// RETURN KEYSTROKE
[delegate doSomethingWhenReturn];
return NO;
}
return YES;
}
I tried to programmatically add "space" when the return key is hit but that also ignores the auto-completed word.
else if ([text isEqualToString:#"\n"]){
// Tryin to accept autocomplete with no result.
textview.text = [textview.text stringByAppendingString:#" "];
// RETURN KEYSTROKE
[delegate doSomethingWhenReturn];
return NO;
}
Any suggestions?
Call -resignFirstResponder (i.e. [textView resignFirstResponder]) on the text view or text field which needs to accept autocomplete results: UIKit will change the .text property to include the autocorrected text.
If you want to keep the keyboard up after your first view resigns first responder, pass the firstResponder responsibility onto your next text input view with [anotherTextView becomeFirstResponder].
For backspace and space u can use this condition
if ([[text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0)
{
[delegate doSomethingWhenBackspace];
return NO;
}
I've had a very similar problem, I was making an app that had to read every letter in a text view and I has issues when Autocomplete inserted words because it was saving it as if it was one letter.
you could add each character to an array and then check to see if any are over 1 string in length. Or you could add each character that is put in into an array and then run something like
NSString *string = text;
NSMutableArray *array = [NSMutableArray new];
for (int i=0; i<string.length; i++) {
[array addObject:[string substringWithRange:NSMakeRange(i, 1)]];
}
to add each character individually, by comparing the two arrays you could determine if autocorrect has been used and with what word/s.
Hope this will help.

Keypressed event in UITextField

I have 10 textfields, in which I could enter only one character in each textfield. After a character is entered in each textfield, the focus should move to the next one. Similarly when i delete character from a textfield by pressing the backspace or delete, i need to get the focus to the previous textfield. If I could get the keypressed event, I could do that. Right now I am not able to find any keypressed event examples.
Implement UITextFieldDelegate.
Implement the delegate methods in the protocol. You can achieve the things you wanted.
You can set the focus by using the method becomeFirstResponder to the required textfield.
Have a look at the delegate method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
The text field calls this method whenever the user types a new character in the text field or deletes an existing character.
So that could solve your problem.
Based on Aadhira's answer, but taking into account Kirk Woll's comment, you can generate what the latest text will be by using stringByReplacingCharactersInRange:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *value = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(#"value: %#", value);
return YES;
}
Just to give you directions:
Assign tag to each text field.
Implement UITextFieldDelegate. There are all the methods you need to detect any event that takes place inside the text field. In each method you can check the tag and move focus properly.
Hint: you can use [mainView viewWithTag:XX] to quickly pick the text field you need.
Each time the text is changed you can check the text property of the text field and it will give you the answer which button was pressed.
you have to implement the UITextFieldDelegate protocol into your code and this method will tell you when you start begin editing in text field
– textFieldShouldBeginEditing:
and you can set the if condition in this method according to your requirement...
You have to use the textfieldDelegate methods.
In your textFieldShouldReturn method you have to set your responders like
if (textfield == textField1)
{
[textField2 becomeFirstResponder];
}
else if (textField == textField2)
{
[textField3 becomeFirstResponder];
}
else
{
[textField3 resignFirstResponder];
}
return YES; // as method return type is BOOL.

Replace a given string with an other on UITextView

On my app I need to do this: when a character is typed on TextView to be saved on a NSString and after that to be replace with '*'. I tried this :
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
NSLog(#"typing...");
text=#"*";
passwordText=textView.text;
NSLog(#"password %#",passwordText);
NSString* nextText = [textView.text stringByReplacingCharactersInRange:range withString:text];
textView.text=nextText;
NSLog(#"next %#",nextText);
NSLog(#"textview.text %#",textView.text);
return YES;
}
where passwordText is the NSString in which I want to save the text introduce from keyboard on UITextView.
The result is this : http://i54.tinypic.com/2cx9ueo.png (here I introduced 'we' and I see this :'*w*e'. Can anyone help me to solve this?
I mention that I must do this using UITextView, and not UITextField.
I can tell you why you get character along with the *, though i am not sure whether your approach is worth to go through this.
make your return statement as NO, this will discard the new key pressed. The YES is currently placing that character next to your programmatic '*'.
Just return a NO in the method if you want the change to be immediate. If you want it to be a little delayed (i.e. first show a character then replace with * like in password fields), return a YES and run another method from the
textView:shouldChangeTextInRange:replacementText: method to be fired after 0.5 seconds (or another number if you like) using a timer.
This new method can replace the last added character or changed character with a *.

Disable a particular key in UI Keyboard

It need to disable '&' key from number and punctuation keyboard, so is it possible to disable a particular key in UIKeyboard?
I don't think it's possible to disable a certain key (unless it's one of the action keys such as the return key) but if you are using a UITextField you can use the - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string delegate method to see if the user pressed the & key and remove it from the string
You cannot do that. However your options are:
create your own custom keyboard not offerring '&' key (too much effort IMO)
If you use UITextField you can validate the text submitted by user: remove '&' and/or inform user that it is not allowed to use '&' (much easier).
EDIT: you can also connect UITextField's "Editing Changed" event to the File's Owner's IBAction and filter out '&' there.
There is one delegate method for textField in which you can block specific characters if you want based on their ASCII values. The method can be written as follows:
-(BOOL)keyboardInput:(id)k shouldInsertText:(id)i isMarkedText:(int)b
{
char s=[i characterAtIndex:0];
if(selTextField.tag==1)
{
if(s>=48 && s<=57 && s == 38) // 48 to 57 are the numbers and 38 is the '&' symbol
{
return YES;
}
else
{
return NO;
}
}
}
This method will permit only numbers and & symbol to be entered by the user. Even if the user presses other characters they won't be entered. And as it is a textField's delegate method you don't need to worry about calling it explicitly.
//Disabling the '<' '>' special characters key in Keyboard in my code
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
NSCharacterSet *nonNumberSet = [NSCharacterSet characterSetWithCharactersInString:#"<>"];
if (range.length == 1)
return YES;
else
return ([text stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
return YES;
}