Is it possible to replace a cell view for the selected cell? I have registered my controller as a data source and delegate. Requests for cell views, row numbers, selection status, etc, all come in nicely. In the cell selection callbacks, I'm trying to have the table view reload the cell with a new view (not the actual data!). Basically, I want the cell view to expand and show more of the underlying data, if it is selected. The problem is that I have no clue how to make the table view ask my controller for a new view. I can see that the view is requesting the cell height, but nothing more.
Calling reloadData on the view works, but it's inefficient and comes with a set of its own problems (animation possibilities, maintaining selection state, etc).
Here is the approach I would take to do this.
@property (nonatomic, strong) NSIndexPath *selectedIndexPath;
Set a property of type NSIndexPath to your controller to store which index path was selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation: UITableViewRowAnimationNone];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath compare:self.selectedIndexPath] == NSOrderedSame) {
// Create your custom cell here and return it.
}
else {
// Should create a normal cell and return it.
}
}
Exactly. Note too that you probably want to deselect. Here's the full code in Swift. Use selectedIndexPath in cellForRowAtIndexPath as appropriate.
// Selecting TableViewController import UIKit
class SelectingTableViewController: UITableViewController
{
internal var selectedIndexPath:NSIndexPath? = nil
override func viewDidLoad()
{
super.viewDidLoad()
tableView.estimatedRowHeight = 68.0
tableView.rowHeight = UITableViewAutomaticDimension
self.clearsSelectionOnViewWillAppear = false;
}
override func tableView
(tableView:UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath)
{
print("did select....")
// in fact, was this very row selected,
// and the user is clicking to deselect it...
// if you don't want "click a selected row to deselect"
// then on't include this clause.
if selectedIndexPath == indexPath
{
print("(user clicked on selected to deselect)")
selectedIndexPath = nil
tableView.reloadRowsAtIndexPaths(
[indexPath],
withRowAnimation:UITableViewRowAnimation.None)
tableView.deselectRowAtIndexPath(indexPath, animated:false)
return
}
// in fact, was some other row selected??
// user is changing to this row? if so, also deselect that row
if selectedIndexPath != nil
{
let pleaseRedrawMe = selectedIndexPath!
// (note that it will be drawn un-selected
// since we're chaging the 'selectedIndexPath' global)
selectedIndexPath = indexPath
tableView.reloadRowsAtIndexPaths(
[pleaseRedrawMe, indexPath],
withRowAnimation:UITableViewRowAnimation.None)
return;
}
// no previous selection.
// simply select that new one the user just touched.
// note that you can not use Apple's willDeselectRowAtIndexPath
// functions ... because they are freaky
selectedIndexPath = indexPath
tableView.reloadRowsAtIndexPaths(
[indexPath],
withRowAnimation:UITableViewRowAnimation.None)
}
}
Have you tried:
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
Then you can specify only your updated cell for reloading. You can also tell your tableview to remember or forget selection status upon reload with:
tableViewController.clearsSelectionOnViewWillAppear = NO;
Then you will also have to deal with the custom view inside
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With