在选择器(UIMenuController)中传递参数

3
我有一个 UIMenuController,在一个集合视图单元格的顶部有一个“删除”菜单项,当用户长按带有第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)
    }
}

我该如何将单元格的索引路径传递给下面的函数?我需要这个信息来从服务器上删除对象。
@objc internal func deleteCell(sender: UIMenuItem) {
    print("delete menu item tapped! print index path of selected collection view cell?")
}
4个回答

2
如@mkeremkeskin所指出的,这里有一个链接到答案的Objective-C版本..但是这个答案是Objective-C版本的,这里你会找到一个Swift 4版本。
您可以子类化UIMenuItem并将indexPath添加到其中!我不得不删除一些代码才能在我的playground中工作,但您已经明白了 :)
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
    }
}

1

您不能直接通过 selector 操作传递信息;相反,您应该将索引路径存储在成员变量中,在长按处理程序中设置并在删除处理程序中使用。

private var indexPathForDeleting: IndexPath? = nil

不要忘记进行清理工作并在不再需要时清除变量。

谢谢,我试图避免使用成员变量,因为这样不够简洁。 - Cesare
嘘,= nil 是多余的。 - Cesare
另一种方法是扩展UIMenuItem并附加一个处理程序块...但根据我的经验,如果你只需要使用一次,这样做可能不值得努力,而且子类化UIKit类可能比第一眼看起来更棘手。 - dr_barto
初始化为nil是不必要的,但有时候明确的代码比简短的代码更好...不知道为什么,但我更喜欢将其放在那里,给我一种掌控的温暖感觉 :) - dr_barto
其实是的,这绝对是最简单和最简洁的解决方法 :) - Cesare

1

0

我是这样解决这类问题的:

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


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

我用的是Swift 4。希望能对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接