I have a simple application where the user inputs information into a series of UITextFields and a few other components in order for the app to populate with information.
I have 4 UITextFields (Name, Event, Subevent and Amount), 1 UITextView (notes), a UIDatePicker and a UISegmentedControl (Status).
The Name, Event, Amount and Status are required, where the Subevent and Notes are optional.
I've put some logic to disable the "Save" BarButtonItem if the the required fields are not filled in; however I'm noticing my logic is not working correctly.
Here's the logic:
- (void) checkTextFields
{
if (([self.nameTextField.text length] != 0 && [self.itemTextField.text length] != 0 && [self.occasionTextField.text length] != 0 && [self.isReceivedSegment selectedSegmentIndex] == 0) || [self.isReceivedSegment selectedSegmentIndex] == 1)
{
NSLog(#"This shouldn't be run if not every field is filled in");
self.saveButton.enabled = TRUE;
}
else
{
NSLog(#"Run");
self.saveButton.enabled = FALSE;
}
}
I'm calling this from the viewDidLoad:
self.saveButton.enabled = FALSE;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkTextFields) name:UITextFieldTextDidChangeNotification object:nil];
[self.isReceivedSegment addTarget:self action:#selector(checkTextFields) forControlEvents:UIControlEventValueChanged];
Problem
The problem is: if I enter the Name, Event and Select a Segment in the SegmentedControl, it SHOULD NOT enable the Save button because the Amount is not filled in.
The same applies if I put in the Name, Amount and Select a Segment, the Save button should not be filled in because the Event is not filled in, yet, it is in both of those situations.
Am I missing something obvious?
Try this:
- (void) checkTextFields
{
if ([self.nameTextField.text length] != 0 && [self.itemTextField.text length] != 0 && [self.occasionTextField.text length] != 0 && ([self.isReceivedSegment selectedSegmentIndex] == 0 || [self.isReceivedSegment selectedSegmentIndex] == 1))
{
NSLog(#"This shouldn't be run if not every field is filled in");
self.saveButton.enabled = TRUE;
}
else
{
NSLog(#"Run");
self.saveButton.enabled = FALSE;
}
}
The way you have implemented your conditions, with the parentheses, it will evaluate true when your selectedSegmentIndex = 1, regardless of the other conditions. Moving around the parentheses like so should work.
Notice that I have moved the parentheses to surround the OR portion of your conditions.
EDIT add these lines to your view did load method to have the form be checked after editing any text field.
[nameTextField addTarget:self action:#selector(checkTextFields) forControlEvents:UIControlEventEditingChanged];
[itemTextField addTarget:self action:#selector(checkTextFields) forControlEvents:UIControlEventEditingChanged];
[occasionTextField addTarget:self action:#selector(checkTextFields) forControlEvents:UIControlEventEditingChanged];
Related
IM having an issue with changing the return keys type while still editing the textfield of my view. So when the user clicks the textfield i have a few checks that change the return type of the keyboard, these checks are placed in - (void)textFieldDidBeginEditing:(UITextField *)textField, when i change the keyboards return key here the code works fine. Im just changing the keyboards retrun key like so [textField setReturnKeyType:UIReturnKeyDone];. So there are 2 textfields username and password. If theres text in both the textfields i want to change the return key to DONE if theres text in only one of the text fields i want to change it to NEXT so i can jump back and forth between the textfields.So now im placing some checks and balances in - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string. Yet the same code im placing in textFieldDidBeginEditing is not working in this function. Ive read a bunch of posts and they all say to remove the text field as the first responder then set the return key and become the responder again, but this messes up my current flow in the respective methods. I also read that i have to call [textfield reloadInputFields] after setting the return key, yet again this does not work. You would think that apple would have fixed a bug like this by now. Anyway does anyone have some input here?
I had to implement an add tag logic that required to change the keyboard return key depending on the text typed into the UITextField. Finding how to change the return key was quite easy, but when I started testing, I noticed that this solution only works for iOS10, but not for iOS9. After spending some time and doing some research, I came up with this workaround, it's not the nicest but at least it works.
if #available(iOS 10.0, *) {
textField.reloadInputViews()
} else {
textField.keyboardType = .numberPad
textField.reloadInputViews()
textField.keyboardType = .default
textField.reloadInputViews()
}
Try it out and Let me know
I have made demo for your question and its running perfect as per your need or you can modify it as per
// This is the Editing Changed Action Event of Both textField Created From StoryBoard
- (IBAction)txtEditingChanged:(UITextField *)sender
{
[sender resignFirstResponder];
[sender becomeFirstResponder];
}
// This is the Editing Did End Action Event of Both textField Created From StoryBoard
- (IBAction)txtEditingEnd:(UITextField *)sender
{
if (txtUserName.text.length == 0 || txtPassword.text.length == 0)
{
[txtUserName setReturnKeyType:UIReturnKeyNext];
[txtPassword setReturnKeyType:UIReturnKeyNext];
}
else
{
[txtUserName setReturnKeyType:UIReturnKeyDone];
[txtPassword setReturnKeyType:UIReturnKeyDone];
}
}
// This is Next And Done Button Events i.e. UITextField Delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == txtUserName && textField.returnKeyType == UIReturnKeyNext && textField.text.length != 0)
{
[txtPassword becomeFirstResponder];
}
else if (textField == txtPassword && textField.returnKeyType == UIReturnKeyNext && textField.text.length != 0)
{
[txtUserName becomeFirstResponder];
}
else
{
// This is your Done Button Event You Can Procced Here
}
return YES;
}
The below code for the most part works when selecting items, the bar button enables, but as soon as I unselect 1 with say 3 still selected, it disables.
How can I use the below code to disable when the count reaches 0 items selected?
- (void)assetsTableViewCell:(WSAssetsTableViewCell *)cell didSelectAsset:(BOOL)selected atColumn:(NSUInteger)column
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Calculate the index of the corresponding asset.
NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;
WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
assetWrapper.selected = selected;
// Update the state object's selectedAssets.
[self.assetPickerState changeSelectionState:selected forAsset:assetWrapper.asset];
// Update navigation bar with selected count and limit variables
dispatch_async(dispatch_get_main_queue(), ^{
if (self.assetPickerState.selectionLimit) {
self.navigationItem.title = [NSString stringWithFormat:#"%# (%lu/%ld)", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName], (unsigned long)self.assetPickerState.selectedCount, (long)self.assetPickerState.selectionLimit];
}
});
}
Below is what needs adjusting.
if (selected == 1) {
self.navigationItem.rightBarButtonItem.enabled = YES;
} else if (selected == 0) {
self.navigationItem.rightBarButtonItem.enabled = NO;
}
selected will give you the state of the current asset so it wouldn't be wise to check this.
We need to check for some kinda global thing; basically to check for previous selections.
Looking at your navigationItem.title, it seems assetPickerState.selectedCount should do the trick.
So... maybe this?? (not sure but anyways...)
if (self.assetPickerState.selectedCount == 0) {
self.navigationItem.rightBarButtonItem.enabled = NO;
}
else {
self.navigationItem.rightBarButtonItem.enabled = YES;
}
Looks like you're only explicitly enabling the button when you have 1 selected (not more than that). Just going out on a whim but this might work (only disable if zero, otherwise enable it).
if (selected == 0) {
self.navigationItem.rightBarButtonItem.enabled = NO;
} else {
self.navigationItem.rightBarButtonItem.enabled = YES;
}
I have a form with more than 10 text fields. I want to check if all are entered. I know the following way to check the same
if ([_fName.text isEqualToString:#""])
Is it the best way even if we have more than 10 text fields? or is there any simpler way?like assign something in storyboard or something?
You can conform your view controller to <UITextFieldDelegate> protocol and implement:
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([textField.text isEqualToString:#""]) {
// your code
}
}
In addition your can check which exactly textField was changed and apply custom validation logic:
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField == self._fName) {
// your code
}
}
You can use textFieldDidEndEditing for tracking text:
- (void)textFieldDidEndEditing:(UITextField *)textField {
switch (textField.tag) {
case NameFieldTag:
// do something with this text field
break;
case EmailFieldTag:
// do something with this text field
break;
}
}
I suggest you do something like below. Note, you will probably want to do more than validate if something exists in the fields. You might want to check validity of dates, numbers, etc as well.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// assuming you have a save bar button or equivalent
// disable it or change it from 'Edit' to 'Save' when you start changing textFields
self.navigationItem.rightBarButtonItem.enabled = NO;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// validate form
if (_textField1.text.length > 0 &&
_textField2.text.length > 0 &&
_textField3.text.length > 0 &&
_textField4.text.length > 0 &&
_textField5.text.length > 0)
{
// Re-enable your bar button or change it from 'Edit' to 'Save'
// if form validates
self.navigationItem.rightBarButtonItem.enabled = YES;
}
}
I have four text fields in a ViewController, and want to disable the keyboard for two of them (textField1 and textField2).
I have tried implementing the following after assigning the text fields as delegates in viewDidLoad
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField) {
if ([self.textField1 isTouchInside] || [self.textField2 isTouchInside] {
return NO;
} else {
return YES;
}
}
However, this disables the keyboard for the ViewController completely, so it will not appear when trying to edit textField3 and textField4. How can I get around this problem?
For example, is there a way to refresh the run textFieldShouldBeginEditing method again after editing ends on a textField?
Also, I know I can create a label to accomplish something similar, but I would prefer to use a text field in my case.
EDIT: So I left out a big detail. I am firing an IBaction when pressing textField1 and 2. However, Lootsch's answer gave me an idea.
In the textField1/2Pressed IB action, I ran the textfield.enable:NO methods, then I re-enabled them when I fired a second action which submitted data to the textfields, such as below
- (IBAction)textField1Pressed:(id)sender {
self.textField.Enabled = NO;
}
- (IBAction)submitToTextField1:(id)sender {
self.textField.text = #"blah blah";
self.textField.Enabled = YES;
}
Albeit, this requires having two entering an exiting actions, but it worked for me. Also, I did not have to manipulate the textFieldShouldBeginEditing method with this solution.
You should disable these two textFields (in code or via IB) or you can disable the user interactions (different appearance, same function):
textField3.enabled = NO;
textField4.enabled = NO;
Or:
textField3.userInteractionEnabled = NO;
textField3.userInteractionEnabled = NO;
The second approach won't change the appearance of the UITextFields, while the first will indicate, that these TextFields are disabled.
something like should do
if (textField==textField1 || textField==textField2) [textField resignFirstResponder];
Please try this
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField==self.textField1 || textField==self.textField2)
{
return NO;
}
else
{
return YES;
}
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)mytextField
{
if((mytextField.tag == 104) || (mytextField.tag == 105) || (mytextField.tag == 106))
{
if(mytextField.tag == 104)
{
point = 50;
// if(textField1.tag == 4)
{
[self showDatePickerWithTitle:#"Select DOB"];
return NO;
}
//
}
}
else
{
retutn YES;
}
//you can also try this piece of code.With tag property of textfield.And make sure your tag is not zero,because the default tag is 0 for the main view.
I have a view with two text fields and two segmented controls. I want each text field to become editable when its corresponding segmented control is selected.
Here is the approach I'm using:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == _textField) {
if (_segmentedControl.selectedSegmentIndex == 0 ||
_segmentedControl.selectedSegmentIndex == 1 ||
_segmentedControl.selectedSegmentIndex == 2 ||
_segmentedControl.selectedSegmentIndex == 3) {
return YES;
} else {
return NO;
}
if (textField == _textFieldTwo) {
if (_segmentedControlTwo.selectedSegmentIndex == 0 ||
_segmentedControlTwo.selectedSegmentIndex == 1) {
return YES;
} else {
return NO;
}
}
}
}
This works for the first segmented control and textfield, but the second text field remains editable regardless of the condition of the second segmented control.
Can anyone tell me where I'm going wrong?
Thanks
The IFs are not nested correctly.
if (textField == _One){
if( 0<= selectedIndex < 4) {
//do something
} else {
return no;
}
if (textField == _Two){
// other stuff
}
}
Can you see that the if(textFieldTwo) is inside the if(textFieldOne) ?
Looks like a simple logic error to me. Your:
if (textField == _textFieldTwo) {
should really be an else if on the first if.
Simply change it to:
} else if (textField == _textFieldTwo) {
and it should start working.