Я думаю, что нашел лучшее решение этой проблемы, используя новейшие GestureRecognisers.Я использую следующий распознаватель жестов LongPress внутри моего базового контроллера TableView.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
[gestureRecognizer addTarget:self action:@selector(longGestureAction:)];
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
-(void)longGestureAction:(UILongPressGestureRecognizer *)gesture{
UITableViewCell *cell= (UITableViewCell *)[gesture view];
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:{
NSIndexPath *ip = [self.tableView indexPathForCell:cell];
[self.tableView setScrollEnabled:NO];
if(ip!=nil){
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureWillBegin:gesture forCell:cell];
UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self ];
//switch the view the gesture is associated with this will allow the dragged view to continue on where the cell leaves off from
[draggedView addGestureRecognizer:[[cell gestureRecognizers]objectAtIndex:0]];
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidBegin:gesture forCell:cell];
}
}
break;
case UIGestureRecognizerStateChanged:{
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidMove:gesture];
}
break;
case UIGestureRecognizerStateEnded:{
UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self];
if(draggedView==nil)
return;
//this does not seem like the best way to do this yet you really don't want to fire one after the other I don't think
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:gesture];
[self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];
[self.tableView setScrollEnabled:YES];
[self.tableView reloadData];
}
break;
// case UIGestureRecognizerStateCancelled:
// case UIGestureRecognizerStateFailed:
// case UIGestureRecognizerStatePossible:
// [self.dragAndDropDelegate dragAndDropTableViewController:self draggingGesture:gesture endedForItem:nil];
break;
default:
break;
}
}
В TableViews, расширяющих этот базовый класс, я добавляю следующее в каждую ячейку в cellForIndexPath TableViewDataSource,
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:nil];
longPress.delegate = self;
[cell addGestureRecognizer:longPress];
и, наконец, все, что вам нужно сделать, это реализовать методы делегата следующим образом:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
[gestureRecognizer addTarget:self action:@selector(longGestureAction:)];
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
-(void)longGestureAction:(UILongPressGestureRecognizer *)gesture{
UITableViewCell *cell= (UITableViewCell *)[gesture view];
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:{
NSIndexPath *ip = [self.tableView indexPathForCell:cell];
[self.tableView setScrollEnabled:NO];
if(ip!=nil){
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureWillBegin:gesture forCell:cell];
UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self ];
//switch the view the gesture is associated with this will allow the dragged view to continue on where the cell leaves off from
[draggedView addGestureRecognizer:[[cell gestureRecognizers]objectAtIndex:0]];
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidBegin:gesture forCell:cell];
}
}
break;
case UIGestureRecognizerStateChanged:{
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidMove:gesture];
}
break;
case UIGestureRecognizerStateEnded:{
UIView *draggedView = [self.draggableDelegate dragAndDropTableViewControllerView:self];
if(draggedView==nil)
return;
//this does not seem like the best way to do this yet you really don't want to fire one after the other I don't think
[self.draggableDelegate dragAndDropTableViewController:self draggingGestureDidEnd:gesture];
[self.dropableDelegate dragAndDropTableViewController:self droppedGesture:gesture];
[self.tableView setScrollEnabled:YES];
[self.tableView reloadData];
}
break;
// case UIGestureRecognizerStateCancelled:
// case UIGestureRecognizerStateFailed:
// case UIGestureRecognizerStatePossible:
// [self.dragAndDropDelegate dragAndDropTableViewController:self draggingGesture:gesture endedForItem:nil];
break;
default:
break;
}
}
Вы можете найти источник для этого здесь .Мне потребовалось много времени, чтобы понять это правильно, поэтому я очень надеюсь, что это сэкономит кому-то еще время.