I am using one third-party library HashtagMentionController. Here is the method which I use
- (void) hashtagMentionController:(HashtagMentionController *)hashtagMentionController onMentionWithText:(NSString *)text range:(NSRange)range {
if ([text isEqualToString:#""]) {
if ([self.arrFinalUUID count] < 1) {
self.userListView.hidden = FALSE;
[self.txtNotes resignFirstResponder];
self.replaceRange = range;
self.matchedNames = [[self.names filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject rangeOfString:text].location != NSNotFound;
}]]mutableCopy];
self.matchedNames = names;
[self.tableHashtag reloadData];
} else {
[self presentViewController:[Common alertWithTitle:NSLocalizedString(#"Alert", #"Message") withMessage:NSLocalizedString(#"You can not select more than 1 user", #"Message") preferredStyle:UIAlertControllerStyleAlert] animated:YES completion:NULL];
}
} else {
NSLog(#"backspace pressed");
}
}
I have added this method in my UITextView when user press #.
Now I want a user to add only one name is textfield. I show an alert when the user adds second but there is a problem in this method when I press backspace and remove all the text still there is a value in that array.
So I want to handle backspace in this method(When there is no user I want to allow the user to remove an old array and add new value)
I can update my question if anyone requires more info.
Thanks in advance.
Using this code you can able to detect backspace:
const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];
int isBackSpace = strcmp(_char, "\b");
if ([self.arrFinalUUID count] < 1) {
if (isBackSpace == -8) {
NSLog(#"Backspace was pressed"); // So you can allow the user to remove an old array.
}
}
You just have to change you conditions with isBackSpace. Let me know if you required more information.
Hope this code will help you.
I didn't understood exactly what your requirement is but, so far I think you can use one of UITextField's delegate method textField:shouldChangeCharactersInRange:replacementString: By using this delegate method you can access every character you type live. Only single character in other words you can get which key is pressed on keyboard.
For more on this method go here for documentation.
For detecting spacebar and backspace keys I use the following code:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Add this condition if you need to know about a specified text field.
if(textField==yourTextField)
{
NSLog(#"Tapped key is:%#",string);
if([string isEqualToString:#" "])
{
NSLog(#"Spacebar tapped.");
}
else if([string isEqualToString:#""]||(string.length==0))
{
NSLog(#"Backspace tapped.");
}
}
return YES;
}
Related
I am making an only number input app (still) in which users press a button, I store a value into a string to display in a label.
Works great for the most part, except I cannot figure out how to prevent users from entering more than one decimal in a single string. .
I looked at this Stack overflow question, but trying to amend the code for my own just resulted in a whole bunch of errors. Does anyone have any advice?
- (void)numberBtn:(UIButton *)sender {
if (self.sales.text.length < 10) {
if(self.sales.text.length != 0){
NSString *lastChar = [self.sales.text substringFromIndex:[self.sales.text length] - 1];
if([lastChar isEqualToString:#"."] && [sender.titleLabel.text isEqualToString:#"."] && [sender.titleLabel.text stringByAppendingString:#"."]){
return;
}
if ([lastChar isEqualToString:#""] && [sender.titleLabel.text isEqualToString:#""]){
self.numbers = #"0.";
}
if ([self.sales.text rangeOfString:#"."].length > 0) {
NSArray *array = [self.sales.text componentsSeparatedByString:#"."];
if (array.count == 2) {
NSString *decimal = array.lastObject;
if (decimal.length > 2) {
return;
}
}
}
}
self.numbers = [NSString stringWithFormat:#"%#%#",self.numbers,sender.titleLabel.text];
self.sales.text = self.numbers;
}
}
Two steps...
Check to see if the button is a decimal .
if yes, see if the current label text already contains a .
If it does, return. If not, continue processing your button input:
- (void)numberBtn:(UIButton *)sender {
NSString *btnTitle = sender.currentTitle;
NSString *curText = self.sales.text;
if ([btnTitle isEqualToString:#"."]) {
if ([curText containsString:#"."]) {
NSLog(#"%# : Already has a decimal point!", curText);
return;
}
}
// whatever else you want to do with the input...
}
I am implementing shortcut substitution for text typed into a UITextField.
For instance, if the text field already contains "a" and he types another "a" after it, I'd replace it with "ä". In another case, if he types "a", then "b", I'd replace it with "XYZ". And if the text contains two consecutive spaces, I like to replace them with a single space.
So, depending on what the user types, I might replace it with either a longer, a shorter, or a same-length text.
The simple way to do that is to implement the [UITextFieldDelegate textField: shouldChangeCharactersInRange: ... delegate function, assign the replacement text to textField.text, and return NO.
But this also requires adjusting the cursor position accordingly, and that's what I'm struggling with, a little.
I am handling this cursor positioning "by hand" currently. It's a bit ugly, and so I wonder if there is a more elegant solution. After all, all the code for handling the cursor position after replacing text (e.g. when selecting, then pasting) is already implemented in the UITextField code anyway. I just wonder if more of it is exposed for needs such as mine and I haven't found it yet.
I really think that you don't need textField:shouldChangeCharactersInRange:replacementString:. There is an easy way to solve your requirements and the solution don't have problems with the cursor.
You should add this line of code in your viewDidLoad (self.textField is your UITextField):
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(shortcut:) name:UITextFieldTextDidChangeNotification object:self.textField];
then, you should add the selector, e.g.:
- (void) shortcut: (NSNotification*) notification
{
UITextField *notificationTextField = [notification object];
if (notificationTextField == self.textField)
{
[self checkDoubleA:notificationTextField];
[self checkDoubleAB:notificationTextField];
[self checkDoubleSpace:notificationTextField];
}
}
Then you only need to add the 3 methods to check your shortcuts:
-(void) checkDoubleA: (UITextField*) textField
{
NSMutableString *string = [textField.text mutableCopy];
NSRange range = [string rangeOfString:#"aa"];
if (range.location == NSNotFound)
{
NSLog(#"string was not found");
}
else
{
[string replaceCharactersInRange:range withString:#"ä"];
}
textField.text = string;
}
-(void) checkDoubleAB: (UITextField*) textField
{
NSMutableString *string = [textField.text mutableCopy];
NSRange range = [string rangeOfString:#"ab"];
if (range.location == NSNotFound)
{
NSLog(#"string was not found");
}
else
{
[string replaceCharactersInRange:range withString:#"XYZ"];
}
textField.text = string;
}
- (void) checkDoubleSpace: (UITextField*) textField
{
NSMutableString *string = [textField.text mutableCopy];
NSRange range = [string rangeOfString:#" "];
if (range.location == NSNotFound)
{
NSLog(#"String was not found");
}
else
{
[string replaceCharactersInRange:range withString:#" "];
}
textField.text = string;
}
You can download a demo of this code here.
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;
}
I am using BSKeyboard Controls to have a next/previous and done button above the keyboard on login fields for username and password.
What I want to achieve is:
- When one of the fields is blank the done button should say 'Done'
- When both fields have at least one character it should say 'Login'
I understand there are multiple ways to check a textfield contents, hasText isEqualToString !=nil etc. But I am trying to check characters here I guess.
I need to know what would be the best location to put an if statement and which to use.
My fields are
self.usernameField
self.passwordField
My Keyboard control is updated like this:
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
OR
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin", #"test");
Updated Method:
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
UITextField *otherTextField;
if (textField == self.passwordField)
{
otherTextField = self.usernameField;
}
else
{
otherTextField = self.passwordField;
}
if ([newText length] > 0 && [otherTextField.text length] > 0)
{
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin",#"Button for Keyboard Controls on Login page");
} else {
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
}
You can implement textField:shouldChangeCharactersInRange:replacementString: of UITextFieldDelegate to execute whatever you want when the user enters a key.
Something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
UITextField *otherTextField;
if (textField == self.passwordField)
{
otherTextField = self.usernameField;
}
else
{
otherTextField = self.passwordField;
}
if ([newText length] > 0 && [otherTextField.text length] > 0)
{
// Your code
}
return YES;
}
EDIT
Instead of using that delegate method,use the event editing changed. You have to set the action for that event with IB or by code, and it would look like this:
- (IBAction) textFieldEditingChanged
{
if ([self.usernameField.text length] > 0 && [self.passwordField.text length] > 0)
{
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin",#"Button for Keyboard Controls on Login page");
} else {
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
}
}
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;
}