iOS16中UIMenuController弃用后,如何检测菜单打开并自定义WebView菜单?
一、替换默认菜单:用UIEditMenuInteraction实现自定义菜单
iOS16起UIMenuController被弃用,要在WKWebView中显示自定义菜单,需给WebView添加UIEditMenuInteraction并实现代理方法:
- 添加交互到WebView
在视图控制器的初始化或viewDidLoad中,创建并添加交互:
class WebViewController: UIViewController, UIEditMenuInteractionDelegate { private var webView: WKWebView! private var editMenuInteraction: UIEditMenuInteraction! override func viewDidLoad() { super.viewDidLoad() // 初始化WebView(省略基础配置代码) webView = WKWebView(frame: view.bounds) view.addSubview(webView) // 添加编辑菜单交互 editMenuInteraction = UIEditMenuInteraction(delegate: self) webView.addInteraction(editMenuInteraction) } }
- 自定义菜单内容
实现editMenuInteraction(_:menuForConfiguration:suggestedActions:)代理方法,返回自定义的UIMenu,可完全替换或保留部分系统默认菜单项:
func editMenuInteraction(_ interaction: UIEditMenuInteraction, menuFor configuration: UIEditMenuConfiguration, suggestedActions: [UIMenuElement]) -> UIMenu? { // 自定义菜单项 let customCopyAction = UIAction(title: "自定义复制", image: UIImage(systemName: "doc.on.doc")) { [weak self] _ in guard let selectedText = await self?.webView.selectedText else { return } UIPasteboard.general.string = selectedText } let shareAction = UIAction(title: "分享选中内容", image: UIImage(systemName: "square.and.arrow.up")) { [weak self] _ in guard let selectedText = await self?.webView.selectedText else { return } let activityVC = UIActivityViewController(activityItems: [selectedText], applicationActivities: nil) self?.present(activityVC, animated: true) } // 组装自定义菜单,也可传入suggestedActions保留系统菜单项 return UIMenu(title: "", children: [customCopyAction, shareAction]) }
二、检测菜单打开:用代理回调替代通知
UIEditMenuInteraction没有对应通知,但可通过editMenuInteractionWillPresentMenu(_:)代理方法监听菜单即将显示的事件,完全替代原来的UIMenuControllerWillShowMenuNotification:
func editMenuInteractionWillPresentMenu(_ interaction: UIEditMenuInteraction) { // 菜单即将打开时执行你的业务逻辑,比如记录状态、更新界面等 print("编辑菜单已触发显示") // 替换你原来在通知回调中的代码 }
辅助:获取WebView选中文本
要处理自定义菜单的文本操作,可给WKWebView扩展获取选中文本的方法:
extension WKWebView { var selectedText: String? { get async { return try? await evaluateJavaScript("window.getSelection().toString()") as? String } } }
内容的提问来源于stack exchange,提问作者mayank kulshrestha
相关产品推荐
相关产品推荐

