aneuryzm
aneuryzm

Reputation: 64834

UITableView: how to disable dragging of items to a specific row?

I have a UITableView with draggable rows and I can add/remove items. The datasource is a NSMutableArray.

Now, if I move the row with "Add new functionality" the app crashes because the dataSource is smaller since such row has not been added yet.

So I've modified this code:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
        if (indexPath.row >= [dataList count]) return NO;
        return YES;
    }

And now I can't move it anymore. However I can still move the other rows after such row and consequently the code crashes.

How can I solve this ? Is there a way to disable the dragging "to" specific rows and not only from ?

thanks

Upvotes: 28

Views: 13476

Answers (5)

Mr.Javed Multani
Mr.Javed Multani

Reputation: 13234

Following is the working solution for disable row from moving.

func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        if indexPath.row == 0{//specify your indexpath row here....
            return false
        }else{
            return true
        }
        
    }

Upvotes: 2

Ashish Gupta
Ashish Gupta

Reputation: 378

Following is the example to restrict drag and drop to 0th index of 1st section UICollectionView:

func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {

    if session.localDragSession != nil {
        // Restricts dropping to 0th index
        if destinationIndexPath?.row == 0 {
           return UICollectionViewDropProposal(operation: .forbidden) 
        }

        if collectionView.hasActiveDrag {
            return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        } else {
            return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)
        }
    }        
}

func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    // Prevents dragging item from 0th index
    if indexPath.row == 0 {
        return [UIDragItem]() // Prevents dragging item from 0th index
    }

    let item = self.yourArray[indexPath.row]
    let itemProvider = NSItemProvider(object: item)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    dragItem.localObject = item
    return [dragItem]
}       

Upvotes: 7

GarlicFries
GarlicFries

Reputation: 8323

This is exactly what the UITableViewDelegate method

-tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

is for. Will it suit your purposes? Here's the documentation.

Upvotes: 46

Matt Fenwick
Matt Fenwick

Reputation: 49085

The previous answers and the documentation (see this and this, as mentioned in the other answers) are helpful but incomplete. I needed:

  • examples
  • to know what to do if the proposed move is not okay

Without further ado, here are some

Examples

Accept all moves

- (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
                         toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    return proposedDestinationIndexPath;
}

Reject all moves, returning the row to its initial position

- (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
                         toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    return sourceIndexPath;
}

Reject some moves, returning any rejected row to its initial position

- (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
                         toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if (... some condition ...) {
        return sourceIndexPath;
    }
    return proposedDestinationIndexPath;
}

Upvotes: 27

WebOrCode
WebOrCode

Reputation: 7284

How to make last row fix:

- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
       toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    // get number of objects
    NSUInteger numberOfObjects = [[[BNRItemStore sharedStore] allItems] count]; 

    if ( (proposedDestinationIndexPath.row+1==numberOfObjects) || (sourceIndexPath.row+1==numberOfObjects) ) {
        NSLog(@"HERE");
        return sourceIndexPath;
    }
    else{
         NSLog(@"count=%d %d", [[[BNRItemStore sharedStore] allItems] count], proposedDestinationIndexPath.row);
        return proposedDestinationIndexPath;
    }
}

Upvotes: 9

Related Questions