You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)
    }
}

关键说明

  1. 代理时机选择:messageAttributedText是MessageKit完成初始文本处理(包括链接检测)后调用的方法,此时修改显示文本不会破坏框架的链接识别逻辑。
  2. 属性完整保留:合并MessageKit设置的样式属性和.link属性,既保证显示样式正确,又确保点击事件能被框架识别。
  3. 倒序替换:避免替换文本后range偏移导致的后续替换错误。

内容的提问来源于stack exchange,提问作者kunass2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:25:47