开发者

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] at开发者_JS百科IndexPath: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.


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.


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!


Mostly same answer as above but with corrected placement of when to call scrollToRowAtIndexPath

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

case NSFetchedResultsChangeInsert:
   [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]  withRowAnimation:UITableViewRowAnimationFade];
   //save new index path into your own ivar
   self.newlyInsertIndex = newIndexPath
break;

if using boiler plate FRC code, cannot scroll to newly inserted index until table updates finished

Do this in method - (void)controllerDidChangeContent:

    if (!self.changeIsUserDriven){

         [self.tableView endUpdates];

        if (self.newlyInsertedIndex){
            //ScrollPositionNone == use least amount of effort to show cell
            [self.tableView scrollToRowAtIndexPath:self.newlyInsertedIndex  
            atScrollPosition:UITableViewScrollPositionNone animated:YES];
            //cleanup
            self.newlyInsertedIndex = Nil;
        }
    }

and add method from UIScrollViewDelegate:

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

remember to add newlyInsertedIndex ivar


This all did not work for me. What I did was:

  • when I create a new object, I remember it in an instance variable _newInstance
  • when the object is saved or the creation cancelled, I clear it: _newInstance = nil;
  • in controllerDidChangeObject I select the row:

    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    {
      [self.tableView endUpdates];
    
      if (_newObject) {
        NSIndexPath *ip = [self.fetchedResultsController indexPathForObject:_newObject];
        [self.tableView selectRowAtIndexPath:ip animated:YES
                        scrollPosition:UITableViewScrollPositionMiddle];
      }
    }
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜