Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to select a row after inserting it?

I'm working on an iOS app using the Navigation based, CoreData template. I would like to select and "scroll to visible" a row after it was inserted into the table view. Ideally i'd like to select it, deselect it and select it again, in order to get a kind of flashing effect.

As i am using the method, that the template provaides, namely:

#pragma mark - Fetched results controller delegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;


    switch(type)
    {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationTop];
                [self.tableView selectRowAtIndexPath:newIndexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];

            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{


    [self.tableView endUpdates];

}  

i am a bit confused and don't know, where to put that selection code.
If i put a
[tableView selectRowAtIndexPath:<#(NSIndexPath *)#> animated:<#(BOOL)#> scrollPosition:<#(UITableViewScrollPosition)#>]
into
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller,
it selects the row, but deselects it immediately and the scrolling doesn't behave as it should either.

like image 469
bijan Avatar asked Jul 02 '11 20:07

bijan


2 Answers

I solved similar problem. I inserted item to beginning of Table and I wanted to select it just right after.

Step 1. - Create a switch to keep state if it shall select first row

@implementation MyTableViewController {
    BOOL _selectFirstRow;
}

Step 2. - Switch it to YES while inserting

- (void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            _selectFirstRow = YES;
            break;

Step 3. - Create a method to select first row

- (void) selectFirstTableRow
{
    [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
                                animated:YES
                          scrollPosition:UITableViewScrollPositionTop];
}

Step 4. - Call the method to select row right after table is updated

- (void) controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
    if (_selectFirstRow) {
        [self selectFirstTableRow];
        _selectFirstRow = NO;
    }
}

That's all folks .. if you want select different row, store newIndexPath in class parameter too. That's all. I hope it will help you. Cia!

like image 30
Lweek Avatar answered Nov 03 '22 09:11

Lweek


in method controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: change this section:

case NSFetchedResultsChangeInsert:
   [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
   [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
   insertedIndexPath = newIndexPath; //remember for selection
break;

and add method from UIScrollViewDelegate:

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
   [self.tableView selectRowAtIndexPath:insertedIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
}

remember to add insertedIndexPath variable.

like image 151
alhcr Avatar answered Nov 03 '22 09:11

alhcr