Callback for cellForRowAtIndexPath? - ios

My Project:
I have an UITableView in My project. Each and every UITableViewCell have one UITextView as a subview. When user tap on 'Add' button, I need to add one more UITableViewCell with UITextView to UITableView and I have to set focus into the added UITextView.
What I've Tried:
Once user tap on add button, I will update the numberOfRowsInSection of UITableView and subsequently I'll call [UITableView reloadData] to invoke [UITableView cellForRowAtIndexPath]. Here, I'll append the UITextView as subview of UITableViewCell.It Works fine until this point.
My problem:
I need to set focus into the UITextView Once after the [UITableView cellForRowAtIndexPath] get called. When I called the set focus method for UITextView after [UITableView reloadData], It is not working. I want to know, Is there any callback method for [UITableView cellForRowAtIndexPath]?
Thanks for your answers.

Try this,
In Add button action
//Assuming only 1 section, if you have more section find sections by `numberOfSections` method
NSInteger totalRows = [self.tableView numberOfRowsInSection:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:totalRows inSection:0];
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
//If you have custom cell
CustomCell *cell = (CustomCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[cell.textView becomeFirstResponder];
//If you are not using custom cell, then set tag to textView and
//UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//UITextView *textView = (UITextView *)[cell viewWithTag:kTextViewTag];
//[textView becomeFirstResponder];

after you have called your reloadData method you can do something like this:
To get a reference to the last row in the last section…
// First figure out how many sections there are
NSInteger lastSectionIndex = [self.myTableView numberOfSections] - 1;
// Then grab the number of rows in the last section
NSInteger lastRowIndex = [self.myTableView numberOfRowsInSection:lastSectionIndex] - 1;
// Now just construct the index path
NSIndexPath *pathToLastRow = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];
//Grab a reference of your cell from the last row
MyCustomCell *myCC = [self.myTableView cellForRowAtIndexPath:pathToLastRow];
//Use this cell reference to set focus to your UITextView
[myCC.myTextView setFirstResponder:YES];

Related

Hide Label from prototype cell in TableView

I am working on Prototype TableView Cell where I have two Label over cell and one button behind the cell. I want to hide the second label on Hide Button click. I have tried a lot but did not get any appropriate info, Here is my code for displaying the Labels in Cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"TableCell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
// Configure the cell...
int row = [indexPath row];
cell.EnglishLable.text = _English[row];
cell.UrduLable.text = _Urdu[row];
return cell;
}
Everything is fine, I just need to hide 'UrduLabel' in my Hide IBAction method.
- (IBAction)Hide:(id)sender {
static NSString *simpleTableIdentifier = #"TableCell";
UITableView *tableView = [[UITableView alloc]init];
CGPoint location = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:IndexPath];
BOOL *hideLabel;
hideLabel = YES;
[self.tableView reloadData];
UILabel *subtitle = (UILabel *)[cell.contentView viewWithTag:1];
subtitle.hidden = hideLabel;
}
Whats wrong in my Button method?
Try this code
- (IBAction)Hide:(id)sender {
CGPoint location = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
TableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.UrduLable.hidden = YES;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:<any row animation you need>];
UILabel *subtitle = (UILabel *)[cell.contentView viewWithTag:1];
subtitle.hidden = hideLabel;
}
You just need to get the particular cell of which the button is clicked, hide the required label and reload the particular cell. And main thing is you need to get an instance of your prototype cell class, not of UITableViewCell
IN CASE ONE BUTTON IN THE VIEWCONTORLLER FOR ALL CELL
Incase of single button toggling the visibility of the UrduLabel, declare the -(IBAction)hide:(sender)id in the yourviewcontroller.m. connect the IBAction of the button from nib/storyboard to the -(IBAction)hide:(sender)id method.
Then follow the following steps
declare a BOOL property variable or ivar inside the view controller. named willShowUrdu.
implement the hide as following:
-(IBAction)hide:(id)sender
{
willShowUrdu = !(willShowUrdu);
[yourTableView reloadData];
}
inside the cellForRowAtIndexPath:
TableViewCell *cell = //whatever the way you get the cell
cell.UrduLabel.hidden = !willShowUrdu;
Thats how toggle the visibility of all UrduLabel under one IBAction.
IN CASE OF EACH BUTTON IN EACH CELL
There is a better way to de-centralize the control to each cell. Move the -(IBAction)hide:(sender)id method to the implementation in the TableViewCell's implementation.
Add the IBAction from nib/storyboard to the moved -(IBAction)hide:(sender)id method.
Take a IBOutlet of the UrduLabel, as seen in above code, it's already taken.
Then the implementation of -(IBAction)hide:(sender)id would be following:
-(IBAction)hide:(sender)id
{
//put your other logic here (if any)
self.UrduLabel.hidden = YES;
}
Welcome to IOS, Happy coding.

Tableview reloadData and getting CGRect of new cell

I have a UITableView with cards. Every time I want to add a new card after pushing the draw button I want it to be moved from the center of the view to the location in the table it should be placed with some basic animation. I have managed to get the destination of the new drawn card with this code:
cellRectInTableDrawnCard = [[self playerCardsTable] rectForRowAtIndexPath:drawnCardIndexPath];
cellInSuperviewDrawnCard = [[self playerCardsTable] convertRect:cellRectInTableDrawnCard toView:[[self playerCardsTable] superview]];
However, to determine the cellRectInTableDrawnCard I need to reload the playerCardsTable with reloadData but this shows the drawn card already. It is just a fraction of a second because I place the new card in the table with an animation which fires just after the reloadData. Doing a reload after the animation is not an option, because I don't have the drawnCardIndexPath then.
Is there a way I can get the rect without reloading the tableview? Or else, is there a way I can hide the new cell after reloadData and show it after the animation is done?
Thanks!
You probably want to insert the row and populate it individually and not do a complete table reload.
The code snippet shows a button that uses insertRowsAtIndexPaths:indexPathArray to add a new row which gives you the cell rect to do you animation stuff.
When you're done with animation just use reloadRowsAtIndexPaths to populate the cell value (show you're card I'd guess).
Use a bool to decide in cellForRowAtIndexPath when you should display the new card (basically after you call reloadRowsAtIndexPaths).
- (IBAction)butAddCardToHandAction:(id)sender {
// Add a blank record to the array
NSString *strCard = #"New Card";
_showCard = NO;
[_arrayHandCards addObject:strCard];
// create the index path where you want to add the card
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(_arrayHandCards.count - 1) inSection:0];
NSArray *indexPathArray = [NSArray arrayWithObjects:indexPath,nil];
// Update the table
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
// Ok - you got a blank record in the table, get the cell rect.
CGRect cellRectInTableDrawnCard = [[self tableView] rectForRowAtIndexPath:indexPath];
NSLog(#"My new rect has y position : %f",cellRectInTableDrawnCard.origin.y);
//Do the animation you need to do and when finished populate the selected cell
_showCard = YES;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
Code to control whats displayed in cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell and use boolean to decide what to show
NSString *strToDisplayInCell;
if (!_showCard)
{
strToDisplayInCell = #"";
}
else
{
NSString *strToDisplayInCell = [_arrayHandCards objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15];
cell.textLabel.text = strToDisplayInCell;
}
return cell;
}

Custom delete button for UITableViewCell without editing mode?

I made a UITableViewCell nib with a button on it. When the button is pressed, I want to delete the cell. The table view isn't in editing mode and I'm not using a standard UITableViewCell delete button.
I could store the row number in the button tag from cellForRowAtIndexPath, and use that to determine the row to delete, but when a cell is deleted, the button tags will be incorrect.
Any ideas how I can identify what button press relates to what row?
Like in this answer:
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
If your button is a subview of cell's content view (as it should be). You can get the index path for the cell with button like this:
UIView *cellContentView = yourButton.superview;
UITableViewCell *cell = cellContentView.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
Then, just delete the cell:
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
if the method the button calls has a signature like:
-(void)action:(id)sender;
sender will be the UIButton that called the action so:
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = [[button superview] superview];
should get you what you want.

Scroll custom UITableViewCell to right above keyboard?

Currently I have a UITableView with custom cells and in each cell there is a UITextField, the problem is that sometimes the UITextField is covered by the UIKeyboard.
So right now I have the Y coordinate for the UIKeyboard and my UITableView is functioning properly with the cells.
So pretty much how can I use that Y coordinate (float), in order to scroll my UITableView to that Y coordinate plus the height of the cell in order to get it right above my UIKeyboard?
Also when I the keyboard hides, how would I reset the UITableView to its normal position that it was in?
Any advice would be appreciated!
Thanks!
CustomCell *cell = (CustomCell*)[[thetextField superview] superview];
CGRect cellRect = [cell convertRect:cell.frame toView:self.view];
float bottomCell = cellRect.origin.y - cellRect.size.height;
if (bottomCell >= keyboardY) {
NSIndexPath *indexPath = [thetableView indexPathForCell:cell];
[thetableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
One or the other of UITableView's
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
I'm guessing that control isn't getting into the if statement. Consider skipping the y-coordinate check in favor of just scrolling the table view regardless of where it is.
CustomCell *cell = (CustomCell *)[[theTextField superview] superview];
NSIndexPath *indexPath = [theTableView indexPathForCell:cell];
[theTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
OK, if you're sure it's getting called, then make sure your indexPath isn't nil, which may happen if cell isn't in the tableView or if it's not a cell.
UITableView adjust itself whenever the keyboard is displayed.
However, it won't do it if you didn't set the UITableViewCellSelectionStyle of your custom cell to UITableViewCellSelectionStyleNone.
i solved by using the below code.
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

Add cells to uitableView Like Mail.app

I want to add cells into UItableView like in mail.app on ipad. In my cells I have UITextFields, and I have change this method to set focus
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath{
NSLog(#"%d",newIndexPath.row);
UITextField* field = (UITextField *) [tblView viewWithTag: newIndexPath.row];
int l_cellNum = field.tag;
if(l_cellNum == 1 && isAddedNewRow == FALSE){
isAddedNewRow = TRUE;
[cellsArray insertObject:#"CC" atIndex:1];
[cellsArray insertObject:#"BCC" atIndex:2];
CGRect tvbounds = [tblView bounds];
[tblView setBounds:CGRectMake(tvbounds.origin.x,
tvbounds.origin.y,
tvbounds.size.width,
tvbounds.size.height)];
NSIndexPath *path1 = [NSIndexPath indexPathForRow:1 inSection:0];
NSIndexPath *path2 = [NSIndexPath indexPathForRow:2 inSection:0];
NSArray *indexArray = [NSArray arrayWithObjects:path1,path2,nil];
[tblView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationTop];
[tblView reloadRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
[field becomeFirstResponder];
}
But when I click to one of the cell i add 2 cells (like mail.app) but my tags for textFields do not updates, and I cant to set focus on it =(. If I call reloaddata method it calls -cellForRowAtIndexPath with this new cells at the beggining and after for all cells, and it will not work too.
It sounds like what you're looking for is a built-in style of cells called UITableViewStyleSubtitle, where you can customize the subtitle just like the iPad Mail.app. Take a look at this page in the iOS documentation. Then, you can set the subtitle of the UITableViewCell to the text that you need.
Additionally, the iOS doc has more information about customizing table view cells.

Resources