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]; } }
精彩评论