简体   繁体   中英

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:

在此处输入图片说明

@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?")
}

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
    }
}

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.

You can subclass menu item to get the necessary object.

An example has been answered here:

Pass value through UIMenuItem of UIMenuController

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM