TTTAttributedLabel全选崩溃:Unrecognized selector sent to instance
这个崩溃问题很明确——你在canPerformAction里允许了selectAll操作,但你的CopyableLabel类并没有实现对应的selectAll(_:)方法,系统找不到这个方法就会抛出unrecognized selector异常。同时,要实现部分文本选择+复制,还需要开启TTTAttributedLabel本身的文本选择支持,否则即使加了全选方法,也没法选中文本。
下面是修改后的完整实现,我会一步步解释关键变动:
class CopyableLabel : TTTAttributedLabel { override init(frame: CGRect) { super.init(frame: frame) setupLabel() } required init?(coder: NSCoder) { super.init(coder: coder) setupLabel() } // 初始化时配置文本选择所需的基础设置 private func setupLabel() { isUserInteractionEnabled = true // 必须开启交互,否则无法响应触摸选择 textSelectionEnabled = true // 开启TTTAttributedLabel的文本选择功能 } override var canBecomeFirstResponder: Bool { return true } // 支持复制、全选操作,也可以根据需求添加剪切/粘贴(如果需要的话) override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { let supportedActions: [Selector] = [ #selector(UIResponderStandardEditActions.copy), #selector(UIResponderStandardEditActions.selectAll(_:)) ] return supportedActions.contains(action) } // 实现系统要求的selectAll方法,完成全选逻辑 @objc func selectAll(_ sender: Any?) { guard let textContent = self.text, !textContent.isEmpty else { return } // 设置选中范围为整个文本 selectedRange = NSRange(location: 0, length: textContent.count) // 更新菜单状态,确保选中状态正确显示 UIMenuController.shared.update() } // 重写copy方法,优先复制选中的部分文本,无选中则复制全部 override func copy(_ sender: Any?) { let pasteboard = UIPasteboard.general if let selectedText = self.selectedText { pasteboard.string = selectedText } else { pasteboard.string = self.text ?? "" } // 复制完成后隐藏菜单 UIMenuController.shared.setMenuVisible(false, animated: true) } // 触发菜单显示的方法(可以根据你的交互逻辑调用,比如长按手势) func showEditMenu() { becomeFirstResponder() let menu = UIMenuController.shared if !menu.isMenuVisible { menu.setTargetRect(bounds, in: self) menu.setMenuVisible(true, animated: true) } } }
关键修改说明:
开启文本选择基础配置:
在setupLabel里开启了isUserInteractionEnabled和textSelectionEnabled,这是TTTAttributedLabel支持文本触摸选择的必要前提,默认这些属性可能是关闭的。实现
selectAll(_:)方法:
这是解决崩溃的核心——系统调用全选菜单时会触发这个方法,我们通过设置selectedRange为整个文本范围来完成全选操作,同时更新菜单状态确保选中效果正确显示。优化复制逻辑:
重写copy方法,优先使用selectedText(TTTAttributedLabel提供的选中文本属性)复制选中的部分,如果没有选中内容则复制全部文本,完美支持部分选择复制的需求。代码结构优化:
把初始化配置抽成单独的setupLabel方法,让代码更清晰;把原来的select方法改名为showEditMenu,语义更明确。
最后,记得给你的Label添加长按手势来触发showEditMenu方法(或者根据你的业务逻辑触发),这样用户长按就能调出编辑菜单,进行部分选择、全选和复制操作了。
内容的提问来源于stack exchange,提问作者kjj8

