如何在Swift的MessageKit中用自定义标题替换检测到的链接?
解决MessageKit替换链接文本后无法触发didSelectUrl的问题
问题根源
你的自定义prettyLinked扩展会提前替换原始文本中的链接,导致MessageKit自带的链接检测器无法识别原始URL,进而无法触发点击回调;同时替换时未完整继承MessageKit设置的样式属性,导致显示异常。
解决方案
移除自定义扩展,利用MessageKit的MessagesDisplayDelegate代理方法,在框架完成链接检测和样式设置后,再修改链接的显示文本,同时保留链接的核心属性以确保点击回调正常触发。
完整代码实现
首先确保你的聊天控制器遵循MessagesDisplayDelegate,并保留原有检测相关方法:
class ChatViewController: MessagesViewController { override func viewDidLoad() { super.viewDidLoad() messagesCollectionView.messagesDisplayDelegate = self // 其他初始化设置... } } extension ChatViewController: MessagesDisplayDelegate { // 自定义链接显示文本的核心方法 func messageAttributedText(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> NSAttributedString? { guard let originalText = message.text else { return nil } let mutableText = NSMutableAttributedString(string: originalText) do { // 复用链接检测器 let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) let fullRange = NSRange(location: 0, length: originalText.utf16.count) let matches = detector.matches(in: originalText, range: fullRange) // 倒序替换避免range偏移问题 for match in matches.reversed() { guard let url = match.url else { continue } let linkRange = match.range // 合并MessageKit的样式属性与链接属性 let baseStyle = detectorAttributes(for: .url, and: message, at: indexPath) let linkAttributes = baseStyle.merging([.link: url]) { $1 } // 创建自定义显示文本并替换原链接 let prettyLink = NSAttributedString(string: "super link 🌼", attributes: linkAttributes) mutableText.replaceCharacters(in: linkRange, with: prettyLink) } } catch { print("链接检测错误:\(error)") } return mutableText } // 保留原有启用检测器的设置 func enabledDetectors(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> [DetectorType] { [.url, .phoneNumber] } // 保留原有链接样式设置 func detectorAttributes(for detectorType: DetectorType, and message: MessageType, at indexPath: IndexPath) -> [NSAttributedString.Key: Any] { [.underlineStyle: NSUnderlineStyle.single.rawValue, .foregroundColor: isFromCurrentSender(message: message) ? UIColor.white : UIColor.black] } // 确保点击回调正常触发 func didSelectUrl(_ url: URL, in message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) { UIApplication.shared.open(url) } }
关键说明
- 代理时机选择:
messageAttributedText是MessageKit完成初始文本处理(包括链接检测)后调用的方法,此时修改显示文本不会破坏框架的链接识别逻辑。 - 属性完整保留:合并MessageKit设置的样式属性和
.link属性,既保证显示样式正确,又确保点击事件能被框架识别。 - 倒序替换:避免替换文本后range偏移导致的后续替换错误。
内容的提问来源于stack exchange,提问作者kunass2
相关产品推荐
相关产品推荐

