UIKit中UIAction菜单使用Selector绑定动作报错的解决咨询
UIKit中UIAction绑定动作的正确实现方式
问题说明
在为UIKit菜单项配置UIAction时,第一个按钮无法绑定动作,报错Cannot find 'action' in scope;尝试修改后又出现Function is unused错误,需要明确通过Selector绑定动作的正确实现方式。
原有代码问题分析
- 第一段代码中,第一个
UIAction的闭包写法错误:直接在闭包内写action: #selector(...)属于语法错误,闭包的作用是执行代码逻辑,而非声明参数。 - 第二段尝试的代码中,调用方法时写成
self.RightSideBarButtonItemTapped(_:)只是引用了方法本身,没有进行实际调用,导致编译器提示“函数未被使用”。
正确实现方式
方式一:直接在UIAction闭包中调用@objc方法(推荐)
这是iOS14+ UIAction的标准用法,无需额外使用Selector,直接在闭包内执行目标方法:
class MessageViewController : UIViewController, UITableViewDelegate { // 正确配置第一个UIAction private lazy var first = UIAction(title: "Edit", image: UIImage(systemName: "pencil.circle"), attributes: [], state: .off) { [weak self] _ in // 直接调用目标方法,传入合适的sender(可传nil或当前UIAction实例,根据方法定义调整) self?.RightSideBarButtonItemTapped(nil) } private lazy var second = UIAction(title: "Second", image: UIImage(systemName: "pencil.circle"), attributes: [.destructive], state: .on) { [weak self] _ in self?.sendMessageRightSideBarButtonItemTapped(nil) } private lazy var third = UIAction(title: "Third", image: UIImage(systemName: "pencil.circle"), attributes: [], state: .off) { _ in print("third") } private lazy var menu = UIMenu(title: "new", children: [first, second, third]) override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white let rightBarButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: nil) if #available(iOS 14.0, *) { rightBarButton.menu = menu } navigationItem.rightBarButtonItem = rightBarButton } // 确保方法标记为@objc,参数类型与调用时传入值匹配 @objc func RightSideBarButtonItemTapped(_ sender: UIBarButtonItem?) { let vc = IceWorldView() present(vc, animated: true) } @objc func sendMessageRightSideBarButtonItemTapped(_ sender: UIBarButtonItem?) { print("Second action triggered") } }
方式二:通过Selector绑定(兼容旧习惯)
如果坚持使用Selector,可在闭包内通过perform(_:with:)执行目标方法:
private lazy var first = UIAction(title: "Edit", image: UIImage(systemName: "pencil.circle"), attributes: [], state: .off) { [weak self] action in // 使用perform配合Selector执行方法 self?.perform(#selector(self?.RightSideBarButtonItemTapped(_:)), with: action) }
关键注意事项
- 闭包内使用
[weak self]避免循环引用,防止内存泄漏。 @objc标记的方法参数类型要和调用时传入的参数匹配。- 不要在闭包内仅写
#selector(...),这只是一个选择器常量,不会触发方法执行。
内容的提问来源于stack exchange,提问作者Mai pa
相关产品推荐
相关产品推荐

