1

This is actually a two part question. First take a look at the code:

//canEditRowAt
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    if tableView.tag == 1000{
        return indexPath.row == 0 ? false : true
        }
    return true
}

//canMoveRowAt
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    if tableView.tag == 1000{
        return indexPath.row == 0 ? false : true
    }
    return true
}

So from this I would expect that it would prevent the row at index 0 from having other cells move to it, but no... as you can see:

enter image description here

I obviously want to prevent it, but can't seem to find any documentation to solve the issue.

The other bit I'm struggling with; if you look at the recording you can see that once I move a cell into any location, a black bar appears behind the cell. I would like to avoid that from happening as well, and have tried several things but nothing has worked.

Any help is appreciated, thanks!

jmsapps
  • 388
  • 2
  • 17

2 Answers2

1

To answer the first question, if you look at the tableView(_:canMoveRowAt:) documentation :

This method allows the data source to specify that the reordering control for the specified row not be shown. By default, the reordering control is shown if the data source implements the tableView(_:moveRowAt:to:) method.

This mainly talks about the reordering control being shown rather than specifically saying it can never be moved. So if you look at your UI, the reordering control is not showing for indexPath.row == 0

I can suggest 2 alternatives:

1. Reverse the move action

override func tableView(_ tableView: UITableView,
                        moveRowAt sourceIndexPath: IndexPath,
                        to destinationIndexPath: IndexPath)
{
    // Reverse the action for the first row
    if destinationIndexPath.row == 0
    {
        // You need the give a slight delay as the table view
        // is still completing the first move animation
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)
        {
            tableView.beginUpdates()
            tableView.moveRow(at: destinationIndexPath,
                              to: sourceIndexPath)
            tableView.endUpdates()
        }
        
        return
    }
    
    // update the data source
}

UITableView reorder move UITableViewCell table view cell swift iOS

2. User a header view

This way you don't have to worry about specify any logic of which cells can move and which cannot as you can have the non movable data in a header view:

override func tableView(_ tableView: UITableView,
                        viewForHeaderInSection section: Int) -> UIView?
{
    if section == 0
    {
        // Customize any view
        let headerView = UIView(frame: CGRect(x: 0,
                                              y: 0,
                                              width: tableView.bounds.width,
                                              height: 100))
        headerView.backgroundColor = .red
        
        let label = UILabel(frame: headerView.bounds)
        label.text = "Header view"
        label.textColor = .white
        label.textAlignment = .center
        headerView.addSubview(label)
        
        return headerView
    }
    
    return nil
}

override func tableView(_ tableView: UITableView,
                        heightForHeaderInSection section: Int) -> CGFloat
{
    if section == 0
    {
        // specify any height
        return 100
    }
    
    return 0
}

UITableView custom header UIView swift iOS

I recommend the second option as it has the better user experience and seems to be the right way of approaching this problem.

To answer your second question, in your cellForRowAt indexPath or custom cell implementation, you probably set the background view of the cell or the contentView to black.

Try setting one of these or both:

cell.backgroundColor = .clear
cell.contentView.backgroundColor = .clear

This should not give you a black background

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
  • I went with the first method, just seemed like too much of a headache for a minor gain to go with the second option. The background color I set to clear but it goes translucent when I move rows and you can still see the border of the cell with a shadow, so weird; I decided to just set it to black instead, oh well. By the way you've answered like three of my questions in a row now, you are the man! Thanks so much. – jmsapps Feb 26 '22 at 06:33
0

Implement tableView(_:targetIndexPathForMoveFromRowAt:toProposedIndexPath:) and ensure row 0 is never returned (return row 1 when proposedDestinationIndexPath is row 0).

tausun
  • 2,154
  • 2
  • 24
  • 36
Dan
  • 1
  • 2