indexPathForRow(at: location) always [0, 0]

382 views Asked by At

I have been reading around but I cannot fix this weird behavior.

I am using a UIContextMenu in a Mac Catalyst app. Whenever the user right clicks in a tableViewCell I need to get the datasource object for that row.

I have implemented the following:

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
    let indexPath = tableView.indexPathForRow(at: location)
    print("location:", location)

    let object = ds[indexPath.row]

    //.... rest of the code
}

The above always prints that the indexPath is (0, 0), even though I have more cells.

I have tried to convert the location to the tableView with the following:

let locationInTableView = view.convert(location, to: tableView)

Then use it with:

let indexPath = tableView.indexPathForRow(at: locationInTableView)

But the result is always the same.

Am I doing something wrong here?

1

There are 1 answers

1
hybridcattt On BEST ANSWER

The value you receive in the callback from the context menu is CGPoint, which is the coordinate of where the click happened in coordinate space of the interaction view. (documentation)

Index paths are not coordinates though, but int indexes of your rows starting from zero.

To achieve what you're trying to do, you need an extra step of asking the table view what's the row index under a given coordinate. The result is optional, and is nil if the click didn't land on top of any row.

One more thing to get the correct result is to use UIContextMenuInteraction's method to get the coordinate within coordinate space of the table view.

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {

    let locationInTableView = interaction.location(in: tableView)
    guard let indexPath = tableView.indexPathForRow(at point: locationInTableView) else {
        // clicked not on a row
        return
    }
    let object = ds[indexPath.row]
        ...
    }
}