I'm trying to make my Core data backed UITableView have reorder ability, After implement all those delegate and some technique for core data mentioned here I found strange behavior. After tap edit button, reorder icon show just fine and I can tap on it, the shadow show up, but when I try to move it to other row, I suddenly lose the focus and the cell move back to its place. Have anyone know the cause of this problem ?
Here is video showing the problem
http://www.youtube.com/watch?v=ugxuLNL7BnU&feature=youtu.be
Here is my code
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
in -tableView:moveRowAtIndexPath:toIndexPath
I tried the code below and just an empty implementation, but the problem still exist, so I don't think this is not a problem.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
_changeIsUserDriven = YES;
NSUInteger fromIndex = sourceIndexPath.row;
NSUInteger toIndex = destinationIndexPath.row;
NSMutableArray *newsArray = [[self.fetchedResultsController fetchedObjects] mutableCopy];
News *news = [self.fetchedResultsController.fetchedObjects objectAtIndex:fromIndex];
[newsArray removeObject:news];
[newsArray insertObject:news atIndex:toIndex];
int i = 1;
for (News *n in newsArray) {
n.displayOrder = [NSNumber numberWithInt:i++];
}
[self saveContext];
_changeIsUserDriven = NO;
}
FetchedResultController delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (_changeIsUserDriven) {
return;
}
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
if (_changeIsUserDriven) {
return;
}
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
{
if (_changeIsUserDriven) {
return;
}
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
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
{
if (_changeIsUserDriven) {
return;
}
[self.tableView endUpdates];
}
Finally I found the problem its because external library that I use, IIViewDeckController, After remove that the problem go away.
This is indeed due to the ViewDeckController. I'm using a port in MonoTouch and still encounter the issue. It is due (more specifically) to the UIPanGestureRecognizer. The gesture recognizer is picking up the pan/drag movement and believing that it is meant for itself, so it cancels the touch being sent to the UITableView.
Unfortunately, there is no UIPanGestureRecognizer.direction (horizonal/vertical) property, but there is a post here: UIPanGestureRecognizer - Only vertical or horizontal regarding how to limit the pan gesture to only a certain direction. You will need to modify the ViewDeckController code where it adds the UIPanGestureRecognizer to use the subclassed version from the question above.
I haven't yet tested this (as its 2am and im done for today!) but will update my answer once I have had time to implement this.
As a quick and dirty fix, you can set
panner.cancelsTouchesInView = NO;
This will allow you to move your items, however it will also have its intended result of not cancelling touches in the view, so, depending on your center view's content, it may result in your users pressing a button when they meant to just swipe the view deck to the side.
Another possibility would be to set this property to NO when you set your table into edit mode, and change it back to YES once you are done.
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