Saving text from multiple UITextFields that have the same property name - ios

So I have a view controller that I created completely programmatically, I didn't use storyboard or a nib file. In it, I have a button, addNew that when pressed, it creates two UITextfields, one for a number, the other for a product, and places it where the "Add New"button was, and moves the button down. Instead of explaining it, here's some code :
-(IBAction)addProduct:(id)sender{
self.numOfProducts += 1;
//To keep track of how many times the button was pressed
NSLog(#"New Product Added");
NSLog(#"# of products: %d", self.numOfMaterials);
//The number textfield
self.numOfProduct = [[UITextField alloc]initWithFrame:CGRectMake(self.addNew.frame.origin.x, self.addNew.frame.origin.y, 70.0, 30.0)];
self.numOfProduct.delegate = self;
self.numOfProduct.textAlignment = NSTextAlignmentCenter;
[self.numOfProduct setPlaceholder:#"#"];
self.numOfProduct.borderStyle = UITextBorderStyleBezel;
self.numOfProduct.keyboardType = UIKeyboardTypeNumberPad;
//Added doneToolbar to close keypad
UIToolbar *doneToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
doneToolbar.barStyle = UIBarStyleBlackTranslucent;
[doneToolbar setItems:[NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneNumPad)],
nil]];
[doneToolbar sizeToFit];
self.numOfMaterialNeeded.inputAccessoryView = doneToolbar;
//Product text field, places it next to numOfProduct text field
self.product = [[UITextField alloc]initWithFrame:CGRectMake(self.numOfProduct.frame.origin.x + 80, self.numOfProduct.frame.origin.y, 200.0, 30.0)];
self.product.delegate = self;
self.product.textAlignment = NSTextAlignmentCenter;
[self.product setPlaceholder:#"Product"];
self.product.borderStyle = UITextBorderStyleBezel;
self.product.autocapitalizationType = UITextAutocorrectionTypeNo;
self.product.keyboardType = UIKeyboardTypeDefault;
self.product.returnKeyType = UIReturnKeyDone;
self.product.clearButtonMode = UITextFieldViewModeWhileEditing;
//Places addNew below the newly created text fields
[self.addNew setFrame:CGRectMake(self.addNewMaterial.frame.origin.x, self.addNewMaterial.frame.origin.y + (self.addNewMaterial.frame.size.height + 10), self.addNewMaterial.frame.size.width, self.addNewMaterial.frame.size.height)];
// add text fields to the UIScrollView
[self.scrollView addSubview:self.numOfMaterialNeeded];
[self.scrollView addSubview:self.material];
}
//Called when done button is pressed for numOfProduct text field
-(void)doneNumPad{
[self.numOfProduct resignFirstResponder];
[self.product becomeFirstResponder];
//Save num in an array
[self.saveNumOfProduct addObject:self.numOfProduct.text];
for (int i = 0; i < [self.saveNumOfProduct count]; i++) {
NSLog(#"%# of ___", [self.saveNumOfProduct objectAtIndex:i]);
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
//Save product in an array
if (textField == self.product) { //
[self.saveNameOfProduct addObject:self.product.text];
}
return YES;
}
The code is working well and fine, BUT, I realized, if I have the self.numOfProduct textField as the first responder, and instead of pressing "Done", I press the self.product textField right away, it won't save the self.numOfProduct.text, same with the self.product.text, it won't save unless I press "Done". How can I do it so that I can efficiently save the text from the textfield property, no matter how many textfields I have on the screen? Is it possible? I appreciate any feedback! And if I haven't been clear enough, lemme know and I'll clear up whatever needs clearing!

I've found the answer! A lot easier than I thought it would be, I completely forgot about the (void)textFieldDidEndEditing:(UITextField *)textField function. All I had to do was save the text in that function, and it saves every time the textfield becomes the responder to another field OR when I press the done button.

Related

Configure "Done" button for multiple picker views

I have a scene in which I want to use picker views to get the input for multiple text boxes. I want each picker view to have a toolbar with a "Done" button that dismisses the picker view. So far I have:
//toolbar with "Done" button for picker views
UIToolbar *pickerToolBar= [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,320,44)];
[pickerToolBar setBarStyle:UIBarStyleBlackOpaque];
UIBarButtonItem *barButtonDone = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(doneWithPicker:)];
pickerToolBar.items = [[NSArray alloc] initWithObjects:barButtonDone,nil];
barButtonDone.tintColor=[UIColor blackColor];
//set up picker views
_pickerOne = [[UIPickerView alloc] init];
_pickerOne.dataSource = self;
_pickerOne.delegate = self;
self.textFieldOne.inputView = self.pickerOne;
self.textFieldOne.inputAccessoryView = pickerToolBar;
What I need is some way for the doneWithPicker method to figure out which text field is currently being edited and call resignFirstResponder.
Use the text field delegate to identify which field is active. (Make sure to set yourself up as the delegate)
#implementation WhateverViewController
{
UITextField *activeTextField;
}
...
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeTextField = textField;
}
Then, in the method that is called when your done button is tapped:
[activeTextField resignFirstResponder];

Issue in deleting the textfield

I have two buttons for adding and deleting the textfields. Adding works fine but when I click on delete it deletes only the last added textfield. Here are my two methods:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
}
-(void)deleteTextField {
[keyTextField removeFromSuperview];
[valueTextField removeFromSuperview];
yAxisDistance = yAxisDistance-35;
}
I know it's an small issue but I am very new to this field so kindly help.
Use this code for remove specific textfield from UIView. But First you have to set tag of every UITextField in view when you create or add it in view.
for ( UITextField* textField in view.subviews )
{
if(textField.tag== 1)
{
[textField removeFromSuperview];
}
}
I think the problem lies with the outlet. Can you check the following:
Open the outlets that are connected to the textifeld in the IB. There should be gray dots inside circles on the left side of the editor. Are they seem correct for both text fields?
Setup a breakpoint inside deleteTextField method and check the two textfields. Verify that both properties are not nil.
PS: You don't need to add tags to your view, using properties is perfectly fine and even better in my opinion. The reason for your problem is something else. Also, you do not need to removeFromSuperview, you can also setHidden:YES.
Sorry that time I was not understand your problem...
I done with this:
Declare one
NSMutableArray *allTextfieldArray;
and initialise in
viewdidload
method..
now do:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
[allTextfieldArray addObject:keyTextField];
[allTextfieldArray addObject:valueTextField];
}
if ([allTextfieldArray count]>0) {
UITextField *txtField = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField removeFromSuperview];
txtField = nil;
UITextField *txtField2 = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField2 removeFromSuperview];
txtField2 = nil;
yAxisDistance = yAxisDistance-35;
}
you store the last textField in your variables keyTextField and valueTextField. So when you call your deleteTextField the last both will be deleted. you must track which textFileds you want exactly to delete.
for example you could give all your textFields a tag number when you create them:
first create an int as counter:
#implementation YourClass {
int tagcounter;
}
in init method set your counter:
tagcounter = 0;
in your addTextField:
keyTextField.tag = tagcounter++;
valueTextField.tag = tagcounter++;
when the delete button is tapped, you must know the textfield tags and pass them to your deleteTextField method. There you could do something like:
-(void)deleteTextFieldWithTag:(int)tagnumber {
for (UIView *view in [self.view subviews])
{
if ([view isKindOfClass:[UITextField class]])
{
if (view.tag == tagnumber || view.tag == tagnumber+1) {
[view removeFromSuperview];
}
}
}

Changing UITextField with UIPickerView, not calling EditingDidChange Action

Having a slight problem here.
The (IBAction) method I have set up for UITextfields EditingDidChange is not being called when the textField is changed when using a UIPickerView as input.
However, it works fine when using keyboard input.
Does the UIPickerView not send out its current selection until it's dismissed or something?
An alternative is to probably use the UIPickerView method, didSelectRow to perform the updates I'm after.
Is there there a unique way I'm unaware of that will get this to work how I want?
I think that you have something like this to setup your text field:
self.citys = #[#"Buenos Aires", #"Bahia Blanca", #"Azul",#"Pigue"];
self.namePicker = [[UIPickerView alloc] init];
self.namePicker.delegate = self;
self.namePicker.dataSource = self;
self.namePicker.showsSelectionIndicator = YES;
self.accessoryView = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(onNameSelection)];
[self.accessoryView setItems:[NSArray arrayWithObject:doneButton]];
self.textField.inputView = self.namePicker;
self.textField.inputAccessoryView = self.accessoryView;
And something like this to set the text when the user finish the selection:
- (void) onNameSelection{
NSInteger row = [self.namePicker selectedRowInComponent:0];
self.textField.text = [self.citys objectAtIndex:row];
[self.textField resignFirstResponder];
}
So... You don't need the action EditingChanged, because you know when the textfield.text is changed.
Maybe you also have something like this to change the text while the user select row in the picker:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
self.textField.text = [self.citys objectAtIndex:row];
}
Again, you know when the textfield.text is changed.
So... Because YOU are the responsible of the changes on the textfield.text YOU are the responsible of call the function associated to the EditingChanged action.

UIKeyboardTypeDecimalPad with negative numbers

I'm working on an iOS app that requires the user to enter numbers into a UITextField using the keyboard type UIKeyboardTypeDecimalPad. However I just realized that there is no support for entering negative numbers, which is a requirement of the application.
Any ideas or thoughts on how I can accomplish this?
You can use a UIToolbar as an input accessory view for your UITextField and put a button with a "+/-" (plus/minus sign in it).
UIToolbar *toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem *plusMinusBbi = [[UIBarButtonItem alloc]initWithTitle:#"+/-" style:UIBarButtonItemStylePlain target:self action:#selector(togglePositiveNegative:)];
toolbar.items = #[plusMinusBbi];
self.textField.inputAccessoryView = toolbar;
I don't believe that something like that is possible right now (since Apple hasn't implemented it yet). The only option would be to design your own keyboard or use a complete ASCII one.
func addToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let plusMinusButton = UIBarButtonItem(title: "+/-", style: .done, target: self, action: #selector(plusMinusAction))
plusMinusButton.tintColor = .black
plusMinusButton.width = UIScreen.main.bounds.width / 3
toolbar.items = [plusMinusButton]
toolbar.barTintColor = #colorLiteral(red: 0.7812563181, green: 0.8036255836, blue: 0.8297665119, alpha: 1)
toolbar.isTranslucent = false
myField.inputAccessoryView = toolbar
}
#objc func plusMinusAction() {
let text = myField.text ?? ""
if text.hasPrefix("-") {
myField.text = String(text.suffix(text.count - 1))
} else {
myField.text = "-\(text)"
}
}
From what I've found apple has yet to implement such a standard keyboard. However it is possible to add UIButtons to any keyboard window. this link should help, or similar tutorial this link should also help
Basically you register a NSNotificationListener to listen for the keyboard coming up. Grab the keyboards frame and add a UIButton to its view. The above link isn't quite what we want but its the right idea.
In appDelegate,
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
- (void)keyboardDidShow:(NSNotification *)note
{
// Get the Very Top Window on the Display. That's where the Keyboard is.
NSInteger topWindow = [[[UIApplication sharedApplication] windows] count] - 1;
UIWindow *keyboard = [[[UIApplication sharedApplication] windows] objectAtIndex:topWindow];
// If the dot has not been created (first time the keyboard has been displayed) create it.
if (self.dot == nil)
{
self.dot = [UIButton buttonWithType:UIButtonTypeCustom];
// Make the dot a subview of the view containing the keyboard.
[keyboard addSubview:self.dot];
// Place the dot in the correct location on the keyboard.
[self.dot setFrame:CGRectMake(0, 427, 106, 53)];
// Set the overlay graphics. (Use TransDecimalDown.png and TransDecimalUp.png for the Alert Style Keyboard.
[self.dot setImage:[UIImage imageNamed:#"DecimalUp.png"] forState:UIControlStateNormal];
[self.dot setImage:[UIImage imageNamed:#"DecimalDown.png"] forState:UIControlStateHighlighted];
// Give the dot something to do when pressed.
[self.dot addTarget:self action:#selector(sendDecimal:) forControlEvents:UIControlEventTouchUpInside];
}
// Bring the dot to the front of the keyboard.
[keyboard bringSubviewToFront:self.dot];
}
- (void)sendDecimal:(id)sender {
// Post a notification that the dot has been pressed. Observing view controllers are then responsible for adding the actual decimal.
[[NSNotificationCenter defaultCenter] postNotificationName:#"DecimalPressed" object:nil];
// Play the Keyboard Click. If the user has these sound effects turned off, the decimal will still click. Sorry. :( (Also, doesn't seem to work on the simulator, no keyboard clicks seem to.)
AudioServicesPlaySystemSound(0x450);
}
sorry for the horrible code format but you get the idea :)
This clearly isn't my best answer.. but i'm unable to delete it since it is accepted.
may this code will help you:
if you want a negative number just use "-"
NSString *fieldString = [NSString stringWithFormat:#"%#",Textfield.text];
NSLog(#"%#",fString);
int fieldValue;
value = [fString intValue];
NSLog(#"%d",fieldValue);
this will work for decimal numbers
double fieldValue;
value = [fString doubleValue];
NSLog(#"%f",fieldValue);
To accomplish the task I came using '.inputAccessoryView' with the textfield
On viewDidLoad
self.textField.inputAccessoryView = [self accessoryViewForTextField:self.textField];
then
- (UIView *)accessoryViewForTextField:(UITextField *)textField{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
view.backgroundColor = [UIColor lightGrayColor];
UIButton *minusButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
[minusButton setTitle:#"-" forState:UIControlStateNormal];
[doneButton setTitle:NSLocalizedString(#"Done", #"Done") forState:UIControlStateNormal];
minusButton.backgroundColor = [UIColor magentaColor];
doneButton.backgroundColor = [UIColor blueColor];
CGFloat buttonWidth = view.frame.size.width/3;
minusButton.frame = CGRectMake(0, 0, buttonWidth, 44);
doneButton.frame = CGRectMake(view.frame.size.width - buttonWidth, 0, buttonWidth, 44);
[minusButton addTarget:self action:#selector(minusTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[doneButton addTarget:self action:#selector(doneTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:minusButton];
[view addSubview:doneButton];
return view;
}
this will add a custom view just above the keyboard as a part of it
finally to get the 'minus'
#pragma mark - IBActions
- (IBAction)minusTouchUpInside:(id)sender
{
NSString *value = self.textField.text;
if (value.length > 0) {
NSString *firstCharacter = [value substringToIndex:1];
if ([firstCharacter isEqualToString:#"-"]){
self.textField.text = [value substringFromIndex:1];
}else{
self.textField.text = [NSString stringWithFormat:#"-%#", value];
}
}
}
- (IBAction)doneTouchUpInside:(id)sender
{
[self.textField resignFirstResponder];
}

How to add multiple UITextfield in iOS 5?

How do I create and add multiple UITextField to my controller?
I can create one, like this:
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5,5,100,25)];
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
But do I need to do that for each UITextField?
Whats the best approach to template UI Controls?
Put it in a loop, offset each text field's Y position and tag each text field:
for (int i = ; i < numberOfTextFieldsNeeded; i++) {
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5, 5 + 35 * i ,100,25)]; // 10 px padding between each view
tf.tag = i + 1; // tag it for future reference (+1 because tag is 0 by default which might create problems)
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
// don't forget to do [tf release]; if not using ARC
}
Then in delegate methods perform actions based on tag of the textField that called each delegate method. For example to switch to next text view when user taps return key:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1];
[nextTextField becomeFirstResponder];
}
Keep in mind that sending messages to nil in Objective-C will not crash so it will be perfectly fine when user taps return key in last text field as UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1]; will return nil, and calling becomeFirstResponder on nil will do nothing. But you can check if nextTextField is nil and do something else then, whatever you like.
You can use interface builder to create a view (bigger than the size that the screen fits) and programmatically add it to a scrollView.
This is in my opinion the best approach.

Resources