UItextField becomeFirstResponder returning No - ios

I have a UITableView of custom UITableViewCells each with two UITextFields in them. When I select a UITextField in the opening view i.e. without scrolling select a UITextField in the opening view. It becomesFirstResponder and I can enter text, as I hit enter all UITextFields in the opening view can becomeFirstResponder but when I get to the end of the UITableViewCells of that opening view and try to load the next UITableViewCell that is currently out of view and set its UITextField to becomeFirstResponder it doesn't work.
I have set up a if statment inside textFieldShouldReturn and it confirms that the textField is returning NO to becomeFirstResponder.
I would like to know how to fix this; I have looked for solutions but have yet to find anything that fits my situation. Below are the UITextFieldDelegates that I am using as I think in here I am supposed to do something like call or load the next UITableViewCell, but I do not know how.
#pragma mark - Textfield Delegates
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
if ([textField isEqual:cell.widthTexField]) {
nWidth = [[sortedItemsArray objectAtIndex:textField.tag] valueForKey:#"w_MM"];
} else if ([textField isEqual:cell.heightTextField]) {
nHeight = [[sortedItemsArray objectAtIndex:textField.tag] valueForKey:#"h_MM"];
}
return YES;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField*)textfield {
int height = self.finishingTableView.frame.size.height;
NSLog(#"%i", height);
self.finishingTableView.frame= CGRectMake(self.finishingTableView.frame.origin.x, self.finishingTableView.frame.origin.y, self.finishingTableView.frame.size.width, 307);
// select correct row
if (textfield.tag > 999999) {
int adjustTag = textfield.tag-1000000; // remove a million so that you have the text fields correct position in the table. (this is only for height textfields)
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:adjustTag inSection:0];
[finishingTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:finishingTableView didSelectRowAtIndexPath:indexPath];
[self.finishingTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
return YES;
} else {
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:textfield.tag inSection:0];
[finishingTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:finishingTableView didSelectRowAtIndexPath:indexPath];
[self.finishingTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
return YES;
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(#"%i", textField.tag+1);
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
BOOL success = [[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
if (success) {
NSLog(#"HypnosisView became the first responder");
} else {
NSLog(#"Could not become first responder");
}
// this means there has been a change in the UItextfield
NSLog(#"%#", selectedItemDictionary);
if (textField.tag < 999999) {
tempFinishingObjectDictionary = [selectedItemDictionary mutableCopy];
if (![textField.text isEqualToString:[selectedItemDictionary objectForKey:#"w_MM"]]) {
tempUpdatedRow = #"T";
// remove kevalues
[tempFinishingObjectDictionary removeObjectForKey:#"updatedRow"];
[tempFinishingObjectDictionary removeObjectForKey:#"new_w_MM"];
// update keyvalues
[tempFinishingObjectDictionary setValue:tempUpdatedRow forKey:#"updatedRow"];
[tempFinishingObjectDictionary setValue:textField.text forKey:#"new_w_MM"];
}
} else {
if (![textField.text isEqualToString:[selectedItemDictionary objectForKey:#"h_MM"]]) {
tempUpdatedRow = #"T";
// remove kevalues
[tempFinishingObjectDictionary removeObjectForKey:#"updatedRow"];
[tempFinishingObjectDictionary removeObjectForKey:#"new_h_MM"];
// update keyvalues
[tempFinishingObjectDictionary setValue:tempUpdatedRow forKey:#"updatedRow"];
[tempFinishingObjectDictionary setValue:textField.text forKey:#"new_h_MM"];
}
}
NSLog(#"%#", tempFinishingObjectDictionary);
[coreDataController editSelectedFinishing:htmlProjID UpdatedNSD:tempFinishingObjectDictionary SelectedRow:selectedItemIndexPathRow];
[SVProgressHUD dismiss];
NSLog(#"%#", selectedItemDictionary);
return YES;
}

In your textFieldShouldReturn when you go to the next cell you should check if two cells out is off the screen (and therefore not existent). If it is iff the screen you should scroll the table by one cell
[tableview setContentOffset:CGPointMake(tableview.contentOffset.x,tableview.contentOffset.y + cellHeight) animated:YES];
You will have to adjust this scrolling to your liking as I don't know how your application flows.

Related

UITableViewController Static and Grouped scrollToRowAtIndexPath not scrolling to correct cell

I have a UITableViewController in which I am using Static Cells that are grouped. Each cell has a UITextField for users to enter info, and at the bottom is a submit button. Upon tapping the button, I verify that they have entered info for each of the fields and if not, I scroll up to that cell/field so that they can complete it.
However, for some reason it is not scrolling to the correct cell when using scrollToRowAtIndexPath:
#pragma mark - Save
- (IBAction)didTapSaveGuestDetails:(ZSSBottomOverlayButton *)sender {
[self checkForFormSubmissionErrors];
}
- (void)checkForFormSubmissionErrors {
// First Name
if (self.nameFirst.text.length == 0) {
[self showAlertWithMessage:NSLocalizedString(#"* Please enter first name", nil) fieldToHighlight:self.nameFirst];
return;
}
[self.view endEditing:YES];
[self submitUpdatedGuestInfo];
}
- (void)submitUpdatedGuestInfo {
}
#pragma mark - Alert
- (void)showAlertWithMessage:(NSString *)message fieldToHighlight:(UIView *)field {
UIColor *redColor = [OTAColors colorWithRed:234 green:85 blue:58];
[RKDropdownAlert title:message backgroundColor:redColor textColor:[UIColor whiteColor] time:2.0];
if (field) {
[self highlightField:field];
}
}
- (void)highlightField:(UIView *)field {
[self.tableView endEditing:YES];
// Color field
if ([field isKindOfClass:[ZSSLargeTextField class]]) {
ZSSLargeTextField *textField = (ZSSLargeTextField *)field;
[textField showWarning];
}
CGPoint pointInTable = [field convertPoint:field.bounds.origin toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInTable];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
This exact implementation works great when using prototype cells, but NOT static.
However, if I use the following it does scroll to the correct cell:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
So, it seems the issue could be in my convertPoint:toView: method?
Any idea what could be preventing it from scrolling to the correct cell?

UITextField becomeFirstResponder not showing cursor for text

I have two UITextFields on each UITableViewRow, and for some reason when I press return on the UIKeyboard one particular rows neither of the two UITextFields will reaspond (the cursor is not visible).
I have a custom UITableViewCell that I am using, I can show you the code for this if you like however I dont think that is the problem as the return key works for 95% of the UITableViewCells. So I was thinking maybe it was how I was handling the delegate methods for the UITextFields?
This is the code I am using for the delegate methods.
-(BOOL)textFieldShouldBeginEditing:(UITextField*)textfield {
int height = self.finishingTableView.frame.size.height;
self.finishingTableView.frame= CGRectMake(self.finishingTableView.frame.origin.x, self.finishingTableView.frame.origin.y, self.finishingTableView.frame.size.width, 307);
// select correct row
if (textfield.tag > 999999) {
int adjustTag = textfield.tag-1000000; // remove a million so that you have the text fields correct position in the table. (this is only for height textfields)
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:adjustTag inSection:0];
[finishingTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:finishingTableView didSelectRowAtIndexPath:indexPath];
[self.finishingTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
return YES;
} else {
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:textfield.tag inSection:0];
[finishingTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:finishingTableView didSelectRowAtIndexPath:indexPath];
[self.finishingTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
return YES;
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(#"%i", textField.tag+1);
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
// this means there has been a change in the UItextfield
NSLog(#"%#", selectedItemDictionary);
if (textField.tag < 999999) {
tempFinishingObjectDictionary = [selectedItemDictionary mutableCopy];
if (![textField.text isEqualToString:[selectedItemDictionary objectForKey:#"mMM"]]) {
tempUpdatedRow = #"T";
// remove kevalues
[tempFinishingObjectDictionary removeObjectForKey:#"updatedRow"];
[tempFinishingObjectDictionary removeObjectForKey:#"new_mMM"];
// update keyvalues
[tempFinishingObjectDictionary setValue:tempUpdatedRow forKey:#"updatedRow"];
[tempFinishingObjectDictionary setValue:textField.text forKey:#"new_mMM"];
}
} else {
if (![textField.text isEqualToString:[selectedItemDictionary objectForKey:#"hMM"]]) {
tempUpdatedRow = #"T";
// remove kevalues
[tempFinishingObjectDictionary removeObjectForKey:#"updatedRow"];
[tempFinishingObjectDictionary removeObjectForKey:#"new_hMM"];
// update keyvalues
[tempFinishingObjectDictionary setValue:tempUpdatedRow forKey:#"updatedRow"];
[tempFinishingObjectDictionary setValue:textField.text forKey:#"new_hMM"];
}
}
NSLog(#"%#", tempFinishingObjectDictionary);
[coreDataController editSelectedFinishing:htmlProjID UpdatedNSD:tempFinishingObjectDictionary SelectedRow:selectedItemIndexPathRow];
[SVProgressHUD dismiss];
NSLog(#"%#", selectedItemDictionary);
return YES;
}
I don't have any idea on where to look or how to find this error as it seems so random, but happens on the same UITextFields every time.
The code above is where I think the problem could lie; however, having logged everything and debugged for several hours, I am starting to think it's a bug with UITextFields in UITableViewCells.
is [[self.view viewWithTag:textField.tag+1] canBecomeFirstResponder] == YES?
also you need to resign the current UITextField before setting the next as the first responder
[textField resignFirstResponder];

Go to next UITextField in different UITableViewCells

I have a UITableView with x number of cells. In some cells there is x number UITextFields. I want the next-button on the keyboard to highlight the next textField. I got it working in the same cell but not when it's supposed to jump to a textField in a different cell. The first textField in each cell has tag 0 and the second tag 1 and so on. This is my code:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
// Fetch current cell
UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
// Tag for next textField
NSInteger nextTag = textField.tag + 1;
UITextField *nextTextField;
for(UITextField *subview in cell.contentView.subviews){
if([subview isKindOfClass:[UITextField class]]){
if(subview.tag == nextTag){
nextTextField = subview;
break;
}
}
}
if(nextTextField){
// Go to next textField
[nextTextField becomeFirstResponder];
} else{
// IndexPath for current cellen
NSIndexPath *indexPath = [travellersTableView indexPathForCell:cell];
UITableViewCell *nextCell;
// While a cell exist at indexPath
while([travellersTableView numberOfSections] > indexPath.section+1){
nextCell = [self tableView:travellersTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section+1]];
if(nextCell){
for(UITextField *subview in nextCell.contentView.subviews){
if([subview isKindOfClass:[UITextField class]]){
if(subview.tag == 0){
NSLog(#"%#", subview.placeholder);
nextTextField = subview;
break;
}
}
}
// Go to next textField or cell
if(nextTextField){
[nextTextField becomeFirstResponder]; NSLog(#"Next!");
break;
} else{
indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section+1];
}
}
}
if(!nextTextField){ [textField resignFirstResponder]; }
}
return NO;
}
The NSLog's behave as expected. I have different placeholders in the textFields and the next one is echoed. Next! is also echoed so it's trying to becomeFirstResponder.
I found the issue. I didn't fetch nextCell from my tableView correctly. This is how it should look like:
nextCell = [travellersTableView cellForRowAtIndexPath:indexPath];
Always start tags from at least 1. Tags equal to zero causes serious problems. An object with tag 0 is often not initialized. Start your tags from 1 and check again.

how to move to next cell/row in table view with textview

i am stuck at this .please help me in sorting out this issue.
this is my image now i have 5 different rows in the table.
if u click on first textfield after editing the first field then i want done button click to goto the second field and open textview and textfield simulatneously(as shown in the image).
The Category Filed is having picker view,The Name field (shown in image),Location is having same as image,price is having a action sheet.
Now i have added code for action sheet of Price Field .Can somebody help me achieve the required.Thanks for help... :)
i am doing something like this but it is not yet worked for me.
the code is:
- (void) textFieldDoneTouched
{
[self.site setValue:textField.text forIndex:selectedRow];
[UIView animateWithDuration:0.3
animations:^{
CGRect f = textFieldContainerView.frame;
f.origin.y = self.view.frame.size.height;
textFieldContainerView.frame = f;
}];
[textField resignFirstResponder];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:selectedRow inSection:0];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
self.tableView.userInteractionEnabled = YES;
[self.view endEditing:TRUE];
[self validateSiteData];
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[self textFieldDoneTouched];
return YES;
}
#pragma mark -
#pragma mark UITextViewDelegate
- (void) textViewDoneTouched
{
[self.site setValue:textView.text forIndex:selectedRow];
[UIView animateWithDuration:0.3
animations:^{
CGRect f = textViewContainerView.frame;
f.origin.y = self.view.frame.size.height;
textViewContainerView.frame = f;
}];
[textView resignFirstResponder];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:selectedRow inSection:0];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
self.tableView.userInteractionEnabled = YES;
[self validateSiteData];
}
#pragma mark - UIActionSheetDelegate
- (void) actionSheet:(UIActionSheet *)actionSheet1 clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0) {
self.site.price = #"Free";
// NSIndexPath *indexPath = [NSIndexPath indexPathForItem:4 inSection:0];
// [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:100];
//[textField resignFirstResponder];
// [textView becomeFirstResponder];
}
else if(buttonIndex == 1) {
self.site.price = #"Paid ($)";
// NSIndexPath *indexPath = [NSIndexPath indexPathForItem:4 inSection:0];
// [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:100];
// [textField resignFirstResponder];
//[textView becomeFirstResponder];
}
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:selectedRow inSection:0];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self validateSiteData];
}
So, you'd like the iPhone's return key to go to the next field, like pressing Tab on a computer keyboard?
One minor note: I'd recommend using the default grey "return" key, not the blue "Done" key in your screenshot. "Done" is for when the user is done filling out the form and the keyboard should disappear; "return" is for going to the next field or row of text, as in Apple's Contacts app.
Like Apple's Contacts app, I'd also recommend that your UITextFields be in the same UITableViewCells as their labels (Category, Name...). I find the text field directly above the keyboard in your screenshot a little confusing. If you do that, then the following implementation of textFieldShouldReturn will make the next cell's text field into the first responder.
- (BOOL) textFieldShouldReturn:(UITextField*)textField {
// Determine the row number of the active UITextField in which "return" was just pressed.
id cellContainingFirstResponder = textField.superview.superview ;
NSInteger rowOfCellContainingFirstResponder = [self.tableView indexPathForCell:cellContainingFirstResponder].row ;
// Get a reference to the next cell.
NSIndexPath* indexPathOfNextCell = [NSIndexPath indexPathForRow:rowOfCellContainingFirstResponder+1 inSection:0] ;
TableViewCell* nextCell = (TableViewCell*)[self.tableView cellForRowAtIndexPath:indexPathOfNextCell] ;
if ( nextCell )
[nextCell.theTextField becomeFirstResponder] ;
else
[textField resignFirstResponder] ;
return YES ;
}
Let me know if you'd like me to post the whole project.

UITextField doesn't get cursor when UITableView scrolles to not visible cell

I have a custom grouped TableView with 5 sections and in total with 50 custom cells of type:
Label | XXX
where XXX can be UITextField, UITextView, UIButton, UILabel. Cells have mixed order in tableView.
To navigate through textFields & textViews i added Next/Prev buttons on my keyboard.
The problem is the when i select txtField and click Next or Prev button, the table scrolls to the needed cell position, but txtField doesn't get the cursor. In order to get the cell with textField/textView i use:
nextCell = [self tableView:_myTableView
cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
I need to search through all cells in tableView, not only through the visible ones.
As i tested, the problem is in this line of code, because if i call:
nextCell = [_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
and the cell is visible, then the txtField gets cursor. However, if i need to jump from cell (section = 1, row = 6) to cell (section =0, row = 3) which is not visible, i get nil.
My full code of button function:
-(void) previousTextField:(id)sender
{
int curTagInd = _editingTextElement.tag;
NSIndexPath *curInd = [self getRowIndexOf:_editingTextElement];
int curSec = curInd.section;
int curRow = curInd.row;
id nextView = nil;
UITableViewCell *nextCell = nil;
do {
curRow--;
if (curRow >=0) {
nextCell = [self tableView:_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];//[_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:--curRow inSection:curInd.section]];
curTagInd--;
if ([nextCell isKindOfClass:[CustomCell class]] || [nextCell isKindOfClass:[CustomLongTextCell class]]) {
do {
nextView = [nextCell viewWithTag:curTagInd];
if ([nextView isEnabled]) {
nextCell = nil;
_editingIndexPath = [NSIndexPath indexPathForRow:curRow inSection:curSec];
break;
}else{
break;
}
} while (nextView != nil && ((![nextView isKindOfClass:[UITextField class]] && ![nextView isKindOfClass:[UITextView class]]) || ![nextView isEnabled]));
}
}
else if(curSec > 0){ //got to previous section
curSec--;
curRow = [self getNumberOfRowsInSection:curSec];
curTagInd = [self getNumberOfRowsInSection:curSec]+1;
}
else{
nextCell = nil;
}
} while (nextCell != nil);
if (nextView != nil) {
[self.myTableView scrollToRowAtIndexPath:_editingIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
Using this code i get inside method textFieldShouldBeginEditing:, but not in textFieldDidBeginEditing:
SOLUTION:
The problem was that the table began scrolling only after the function previousTextField: was finished, and thus, [textField becomeFirstResponder]; was called before the table was scrolled to the needed position. Due to the fact that needed cell is still not visible on the screen, delegate methods didn't call.
To avoid this, i added timer after table-scrolling line:
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 0.2
target: self
selector:#selector(doneScrolling)
userInfo: nil repeats:NO];
and defined doneScrolling like:
-(void)doneScrolling
{
NSLog(#"done scrolling");
[self tableView:self.myTableView didSelectRowAtIndexPath:self.editingIndexPath];
}
where:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIView *nextView = [cell viewWithTag:indexPath.row+1];
if ([nextView isKindOfClass:[UITextView class]] || [nextView isKindOfClass:[UITextField class]]) {
if ([nextView isEnabled]) {
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
}

Resources