Cesare
Cesare

Reputation: 9419

Passing parameter in selector (UIMenuController)

I have a UIMenuController with a "Delete" menu item on top of a collection view cell which is displayed when the user long presses on a cell with section 1:

enter image description here

@IBAction func handleLongPressOnCell(_ sender: UILongPressGestureRecognizer) {
    let p = sender.location(in: collectionView)
    guard sender.state == .began, let indexPath = self.collectionView.indexPathForItem(at: p), let cell = self.collectionView.cellForItem(at: indexPath) else { return }

    if indexPath.section == 1 {
        let frameInSuperView = collectionView.convert(cell.frame, to: view)
        let deleteItem = UIMenuItem(title: "Delete", action: #selector(deleteCell))
        UIMenuController.shared.menuItems = [deleteItem]
        UIMenuController.shared.setTargetRect(frameInSuperView, in: view)
        becomeFirstResponder()
        UIMenuController.shared.setMenuVisible(true, animated: true)
    }
}

How do I pass the index path of the cell to the function below? I need this information to delete the object from the server.

@objc internal func deleteCell(sender: UIMenuItem) {
    print("delete menu item tapped! print index path of selected collection view cell?")
}

Upvotes: 3

Views: 1462

Answers (4)

Nomanur
Nomanur

Reputation: 336

I solved this type of issue in this way:

let menuController = UIMenuController.shared
menuController.accessibilityHint = String(indexPath.row)


@objc func deleteCell(_ sender: UIMenuController) {
     print("delete menu item tapped! index path? \(sender.accessibilityHint)")
}

I had using swift 4. Hope it will help.

Upvotes: 0

Laffen
Laffen

Reputation: 2771

As @mkeremkeskin pointed out, there's an answer to this where he linked.. but that answer is in Objective-C, here you'll find a Swift 4 version.

You can subclass the UIMenuItem and add the indexPath to it! I had to remove some code for it to work in my playground, but you get the idea :)

class CustomMenuItem: UIMenuItem {
    var indexPath: IndexPath?

    convenience init(title: String, action: Selector, indexPath: IndexPath? = nil) {
        self.init(title: title, action: action)

        self.indexPath = indexPath
    }
}

class ViewController {

    func handleLongPressOnCell(_ sender: UILongPressGestureRecognizer) {

        let indexPath = IndexPath(item: 0, section: 1)

        if indexPath.section == 1 {
            let deleteItem = CustomMenuItem(title: "Delete", action: #selector(deleteCell), indexPath: indexPath)
            UIMenuController.shared.menuItems = [deleteItem]
            UIMenuController.shared.setMenuVisible(true, animated: true)
        }
    }

    @objc internal func deleteCell(sender: CustomMenuItem) {
        guard let indexPath = sender.indexPath else { return }

        // Delete item based on indexPath
    }
}

Upvotes: 2

mkeremkeskin
mkeremkeskin

Reputation: 644

You can subclass menu item to get the necessary object.

An example has been answered here:

Pass value through UIMenuItem of UIMenuController

Upvotes: 1

dr_barto
dr_barto

Reputation: 6085

You cannot directly pass the info along with the selector action; instead you should store index path in a member variable which you set in your long-press handler and consume in your delete handler.

private var indexPathForDeleting: IndexPath? = nil

Don't forget to do your housekeeping and clear the variable when it's no longer needed.

Upvotes: 1

Related Questions