I have a UITableView as a subview of a View. In the ViewController when the table is being populated I'm highlighting one of the rows and keeping a record of the indexPath for that row. I'm doing this in the cellforRowAtIndexPath method.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
favouriteCellView *cell = [tableView dequeueReusableCellWithIdentifier:#"reuseID"];
QBCOCustomObject *favouriteObject = [_favouriteResults objectAtIndex:indexPath.row];
if (favouriteObject.userID == self.user.ID) {
UIView *bgColor = [[UIView alloc] init];
bgColor.backgroundColor = [UIColor colorWithRed:173.0f/255.0f green:146.0f/255.0f blue:237.0f/255.0f alpha:.5];
self.highlightedRowIndex = indexPath;
[cell setSelectedBackgroundView:bgColor];
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
return cell;
}
Then in the viewDidAppear Method I want the table to scroll to the highlighted cell.
-(void)viewDidAppear:(BOOL)animated{
[self.tableView scrollToRowAtIndexPath:self.highlightedRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
However I've double checked that the method is being hit with a breakpoint, but unfortunately the highlighted row is not being scrolled to the top of the table as I'd expected. AM I misunderstanding the scrollToRowAtIndexPath method? Or have I left something out of the above code.
If the row is not on screen, it will not yet be loaded by the table view. This means your cellForRowAtIndexPath for that cell will not yet be called. You'll want to choose this index in a way that does not depend on the view loading. Try this before you call scrollToRowAtIndexPath:
NSInteger row = 0;
for (QBCOCustomObject *object in _favouriteResults) {
if (object.userID == self.user.ID) break;
row++;
}
self.highlightedRowIndex = [NSIndexPath indexPathForRow:row inSection:0];
Related
I had a problem with table view didSelect method and prepareForSegue. I used SWRevealController in my app. While selecting cell it reveals the view. Sometimes it not worked properly. It takes two taps to reveal the view. A few months back I used old reveal view frame which contains perform block action. Its worked perfectly.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (int i=0; i<6; i++)
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
if (i == indexPath.row)
{
cell.contentView.backgroundColor = [UIColor colorWithRed:KColorRedSelected green:KColorGreenSelected blue:KColorBlueSelected alpha:1];
}
else
{
cell.contentView.backgroundColor = [UIColor colorWithRed:KColorRed green:KColorGreen blue:KColorBlue alpha:1];
}
}
}
Add this code inside of didSelectRowAtIndexPath and didDeselectRowAtIndexPath functions
dispatch_async(dispatch_get_main_queue(), ^{
//Write code what you need
});
That works for me.
The problem is with this line
[self tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
You are calling the delegate method, which dequeues a reusable cell (I assume, since it's standard behavior). You do not want to dequeue a reusable cell, you want to do something with a cell that is currently displayed at indexPath. To do that use method from UITableView
[tableView cellForRowAtIndexPath:indexPath];
The full code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// grab the selected cell and give it selected color
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithRed:KColorRedSelected green:KColorGreenSelected blue:KColorBlueSelected alpha:1];
}
- (void)tableView:(UITableView*)tableView didDeselectRowAtIndexPath:(NSIndexPath*)indexPath
{
// grab the deselected cell (if it's still visible) and give it deselected color
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithRed:KColorRed green:KColorGreen blue:KColorBlue alpha:1];
}
You will also need to set appropriate color in UITableViewDelegate method cellForRowAtIndexPath, since the color you once set will stay in the cell when it's reused.
This s completely wrong method to get clicked cell
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
And don't use for loop as well. instead of this you should use
UITableViewCell *cell = [tableView cellForIndexPath:indexPath];
to get correct cell.
I have a long list of data to show in a UITableView. One cell of the table contains many things like comments, share and like. Now when user likes a post in the cell it reloadTableData and move to the first one again.For example user have scrolled down to 30 cells and then like 29th cell, it'll reload the data and goes to the top again.So how to make it stays at the same place after reloading the data? Here is my code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return imagesArr.count;
}
And for the implmemtation of Like button
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HomeCell *cellObj = (HomeCell*)[tableView dequeueReusableCellWithIdentifier:#"HomeCell" ];
cellObj.likeBtn.tag=indexPath.row;
[cellObj.likeBtn addTarget:self action:#selector(loveButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
return cellObj;
}
loveButtonClicked button clicked.
-(void)loveButtonClicked
{
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:nil, nil];
[[RRDataAcessLayer sharedDataAccessLayerManager]sendRequestToFetchHomeData:dict];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeAnnularDeterminate;
// hud.labelText = #"Loading Data";
}
Image below will give you an idea. two cells are given and when the heart icon is tapped it reloads to update the value of total love.
Saved edited index in variable
Get indexpath for that index
Scroll to table after reoladdata to that index
NSIndexPath* ip = [NSIndexPath indexPathForRow:editedRowNumber inSection:0];
[self.tableViewTimeline scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:YES];
If your table view has one section you can pass zero if has number of section you have to pass section in which user edit cell
in like button action you can reload cell without scrolling by using both ways while best just reload selected index as suggest #Mhesh
int selectedIndex=(int) btn.tag;
int likes = [[self.arrayDataSource objectAtIndex:selectedIndex] intValue]+1;
[self.arrayDataSource replaceObjectAtIndex:selectedIndex withObject:[NSString stringWithFormat:#"%d",likes]];
NSIndexPath* ip = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
/*
[self.refWeakTableView reloadData];
[self.refWeakTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionNone animated:YES];
*/
[self.refWeakTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:ip]withRowAnimation:UITableViewRowAnimationNone];
and cell for row method set like button tag
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"MyTableViewCell";
myTableViewCell *cell = (myTableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"myTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// DataSourceModel* dbObject = (DataSourceModel*)[self.arrayDataSource objectAtIndex:indexPath.row];
cell.myCellLabel.text = [NSString stringWithFormat:#"%#",self.arrayDataSource[indexPath.row]];
int indexed = (int)indexPath.row;
cell.btnLike.tag = indexed;
return cell;
}
If action is like affected to one cell then why you reload the whole table, reload the only single cell using below code
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
You can change UITableViewRowAnimation.
I'd recommend to cache the current selection in didSelectedCellAtIndexPath in your Controller and if you reload the whole table you could scroll to this last cached indexPath with the tableView's methods for scrolling. :)
You should not reload all table data, but only the rows you want. You can do this by calling this method on tableView reloadRowsAtIndexPaths(_:withRowAnimation:)
It will reload only desired cells with a desired animation without scrolling to top of table view
I have more than 20 cells in my custom table view, in execution time 6 cells will be visible. Now i select the 4 th cell means, that 4th cell have to come in first position and 5th cell in 2nd position and so on. how to do this process, i tried like this.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MACalendarCustomCell *cell = (MACalendarCustomCell*) [tableView dequeueReusableCellWithIdentifier:[MACalendarCustomCell reuseIdentifier]];
if(cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"MACalendarCustomCell" owner:self options:nil];
cell = customCell;
customCell = nil;
}
cell.lbl_CalendarTitle.text = [arr_CalendarTitle objectAtIndex:indexPath.row];
cell.lbl_CalendarSubTitle.text = [arr_CalendarSubTitle objectAtIndex:indexPath.row];
cell.lbl_calendarEventTime.text = [arr_CalendarEventTime objectAtIndex:indexPath.row];
cell.lbl_calendarDate.text = [arr_CalendarDate objectAtIndex:indexPath.row];
cell.lbl_CalendarMonth.text = [arr_CalendarMonth objectAtIndex:indexPath.row];
cell.lbl_CalendarYear.text = [arr_CalendarYear objectAtIndex:indexPath.row];
cell.img_BackGround.image = [UIImage imageNamed:#"calendar_Cell_Up.png"];
//here click event is occurred.
cell.btn_CollapseExpand.tag = indexPath.row;
[cell.btn_CollapseExpand addTarget:self action:#selector(method_Expand:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
ButtonPressed event calls
- (void)method_Expand:(UIButton*)sender
{
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexpath = [tbl_CalendarList indexPathForCell:cell];
[tbl_CalendarList moveRowAtIndexPath:[NSIndexPath indexPathForItem:indexpath.row inSection:indexpath.section] toIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexpath.section]];
int_SelectedIndex = sender.tag;
NSLog(#"Selected Button : %ld",(long)int_SelectedIndex);
if ( int_TempSelectedIndex != int_SelectedIndex)
{
int_TempSelectedIndex = int_SelectedIndex;
}
else
{
int_TempSelectedIndex = -1;
}
[tbl_CalendarList reloadData];
}
Resizing the cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == int_TempSelectedIndex )
{
cellSize = 300;
isRowSelected[indexPath.row] = YES;
}
else
{
cellSize = 100;
isRowSelected[indexPath.row] = NO;
}
return cellSize;
}
Now i got Like this in simulator.
when i pressed it comes like this.
This selected cell should come to first position.
You can scroll your table view to that cell and you can specify that you want to scroll it on top when you select the cell:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Hope this is what you are after.
In the method_Expand method after fetching the selected row you have to remove the object at the selected index and insert the removed object at 0 index.
Also you want to move the move next item to the second position
For that you have to increment the selected index and check if that index is with in the array bounds then remove that item and add it to the index 1;
- (void)method_Expand:(UIButton*)sender
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexpath = [tbl_CalendarList indexPathForCell:cell];
int nextIndex=indexpath.row+1;
// first remove the object
NSString *str=[arr_CalendarTitle objectAtIndex];
[arr_CalendarTitle removeObjectAtIndex:indexpath.row];
[arr_CalendarTitle insertObject:str atIndex:0];
//do the same to arr_CalendarEventTime,arr_CalendarDate,arr_CalendarMont etc
if([arr_CalendarTitle count]-1<nextIndex)// check if nextIndex within bounds to avoid crash
{
// remove next object and addit to the index 1 to all array
}
[tbl_CalendarList reloadData];
}
As i wrote in the comments:
Upon selection, move selected arr_CalendarTitle entry to the top of array and call reloadData() on tableView. Table view displays data as is sorted in arr_CalendarTitle.
moveRowAtIndexPath is not enough, must resort the array too.
So, before reloadData() call (in button click method), do this:
id object = [[[arr_CalendarTitle objectAtIndex:int_SelectedIndex] retain] autorelease];
[arr_CalendarTitle removeObjectAtIndex:int_SelectedIndex];
[arr_CalendarTitle insertObject:object atIndex:0];
For ARC you can use :
__autoreleasing id object = [arr_CalendarTitle objectAtIndex:int_SelectedIndex];
[arr_CalendarTitle removeObjectAtIndex:int_SelectedIndex];
[arr_CalendarTitle insertObject:object atIndex:0];
Since you have more than one array that holds data (only noticed that now) you must do this for every array thats holds data for tableView cells.
Use below method to scroll your tableview.
[tableview setContentOffset:CGPointMake(0, button.tag*tableview.rowHeight) animated:YES];
This method will make tableview scroll to specified point.
Change value of Y in CGPointMake according to your code.
I am trying to scroll my UITableViewCell up one UITableViewCell position when the selected cell reaches the last position in the UITableView
I have the logic correct for identifying the last visible UItableViewCell of the UITableView. However the code to make the UITableView scroll up one position is not working. This is the code I have written.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
cellSelectedBool = YES;
cell = (CustomFinishingCell *)[tableView cellForRowAtIndexPath:indexPath]; // error
[cell.widthTexField becomeFirstResponder];
// Gets an array of current visible cells in UITableView
NSArray *visibleCells = [tableView visibleCells];
NSLog(#"%#", visibleCells);
// get indexpath of last cell
UITableViewCell *lastCell = [visibleCells lastObject];
NSIndexPath *lastCellIndex = [finishingTableView indexPathForCell:lastCell];
// perform scroll when last visible cell is selected
if (indexPath.row == lastCellIndex.row) {
NSLog(#"BIGGER");
int cellHeight = 44;
[UIView animateWithDuration:.25 animations:^{
[finishingTableView setContentOffset:CGPointMake(finishingTableView.contentOffset.x,finishingTableView.contentOffset.y + cellHeight) animated:YES];
}];
}
you should use:
NSIndexPath *rowToSelect; // assume this exists and is set properly
UITableView *myTableView; // assume this exists
[myTableView selectRowAtIndexPath:rowToSelect animated:YES scrollPosition:UITableViewScrollPositionNone];
[myTableView scrollToRowAtIndexPath:rowToSelect atScrollPosition:UITableViewScrollPositionNone animated:YES];
if (indexPath.row == lastCellIndex.row) {
[finishingTableView scrollToRowAtIndexPath:indexPathatScrollPosition:
UITableViewScrollPositionNone animated:YES];
}
I have an iPad app which uses a UISplitViewController (with a UITableView on the left and a detail view on the right). My table view highlights the selected cell in blue when you tap on it.
When I call the following method, the cell is selected but not highlighted in blue:
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
I have spent literally days fiddling about with various delegate methods and hacks trying to get the cell to highlight programatically just as if it had been tapped. I can't do it.
I've managed to almost get there with this:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (shouldHighlightCell)
{
NSIndexPath *indexPathForCellToHighlight = [NSIndexPath indexPathForRow:0 inSection:0];
if ([indexPath isEqual:indexPathForCellToHighlight])
{
cell.selected = YES;
shouldHighlightCell = NO;
}
}
}
It works as long as I also have this (otherwise it remains selected even when another cell is tapped):
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *ip = [NSIndexPath indexPathForRow:0 inSection:0];
if ([[self.tableView cellForRowAtIndexPath:ip] isSelected])
{
[[self.tableView cellForRowAtIndexPath:ip] setSelected:NO];
}
NSIndexPath *iToTheP = indexPath;
return iToTheP;
}
I know this is a weird and convoluted workaround. I wouldn't mind, but it doesn't even work fully. The selected cell loses its highlight if it is scrolled off screen, whereas a cell that has been tapped remains highlighted when scrolled off screen.
I'm absolutely baffled by this. I'm sure this workaround shouldn't even be necessary, that there is a much simpler solution.
Please be sure the cell's selectionStyle is UITableViewCellSelectionStyleBlue and the tableView's allowsSelection is set to YES.
The method selectRowAtIndexPath:animated:scrollPosition: works fine for me. It does highlight the selected cell.
I went through and tried all these and other solutions and no joy. In my case the problem (which drove me nuts for 2 hrs) was the following - shortly after I was calling selectRowAtIndexPath, I was calling reloadData on the tableview. That reload was wiping all the highlighting! Beware of this pitfall! With the unnecessary reloading of data call gone, the highlighting happenned as expected.
I also tried many approaches to get the initial selection to display on my single-selection UITableView. What finally worked for me was to defer the selection of the initial row until the table was set up by calling it in my UITableViewController's viewDidAppear:
override func viewDidAppear(animated: Bool)
{
tableView.selectRowAtIndexPath(indexPathToSelectInitially, animated: false, scrollPosition: .None)
}
I found this and it works for me (aka calling the delegate method didSelectRowAtIndexPath)
NSIndexPath *defaultIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self tableView:[self tableView] didSelectRowAtIndexPath:defaultIndexPath];
PS. I'm using UITableViewController.
I found this to be completely unfixable using all known possibilities. In the end I fixed it by ditching a lot of my code and switching to NSFetchedResultsController instead. NSFetchedResultsController was introduced shortly after I originally wrote this app, and it greatly simplifies the process of using Core Data with UITableViews.
https://developer.apple.com/library/IOs/documentation/CoreData/Reference/NSFetchedResultsController_Class/index.html
It gets the backgroundview with cell border looking like seperator.Do not change the default tableview settings in Interface builder.Make sure UITableViewCellSelectionStyleNone is NOT set to selectionstyle. I am pasting the working code. :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *kCellIdentifier = #"PlayListCell";
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellIdentifier];
}
MPMediaPlaylist *playList = [playlistCollection objectAtIndex:indexPath.row];
cell.textLabel.text = playList.name;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d Songs",[playList.items count]];
MPMediaItemCollection *playListMediaCollection = [playlistCollection objectAtIndex:indexPath.row ];
cell.imageView.image =[UIImage imageWithCGImage:[self getImageForCollection:playListMediaCollection.items]];
// the main code which make it highlight
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor colorWithRed:170.0f/255.0 green:170.0f/255.0 blue:170.0f/255.0 alpha:1.0f];
[bgColorView.layer setBorderColor:[UIColor blackColor].CGColor];
[bgColorView.layer setBorderWidth:1.0f];
[cell setSelectedBackgroundView:bgColorView];
return cell;
}