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

如何在UITextView中添加可点击超链接触发自定义函数实现类维基弹窗

UITextView 应用内自定义可点击链接实现

核心逻辑

不用让自定义URL走系统跳转流程,所有点击拦截都可以在UITextView的代理回调里完成。自定义URL本质上只是一个携带点击标识的传输载体,不需要真的被系统解析打开。

实现步骤

1. 设计自定义URL规则

自己定一套方便解析的URL格式就行,完全不需要和系统做关联,比如统一用wiki://term/{词条ID}的结构:

  • scheme字段可以随便定,比如示例里用的wiki
  • host字段存业务需要的参数,比如词条唯一ID、对应功能的路由值

举个例子:要给“增强现实”这个词汇绑定词条数据,就把链接属性的值设为wiki://term/arkit
这类纯内部拦截用的自定义URL,完全不需要在Info.plist里注册URL Scheme,因为根本不会把URL交给系统处理。

2. UITextView基础配置

先把基础属性配好,不然链接根本点不动:

  • 关闭编辑能力:isEditable = false
  • 开启文本可选能力:isSelectable = true
  • 绑定代理对象:delegate = self

3. 构造带链接的富文本

给需要可点击的文字范围挂上.link属性,属性值就是你设计好的自定义URL。

4. 拦截点击事件,触发自定义交互

在UITextView的代理方法里匹配自定义的URL scheme,解析出携带的参数,调用你自己实现的维基样式弹窗函数,最后返回false阻断系统默认的打开行为。

下面是完整可运行的示例代码:

class ViewController: UIViewController, UITextViewDelegate {
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // 必配置项,否则链接无响应
        textView.isEditable = false
        textView.delegate = self
        
        // 构造富文本内容
        let fullText = "ARKit 是苹果推出的增强现实开发框架,其中屏幕空间环境光遮蔽可以显著提升渲染真实感。"
        let attributedString = NSMutableAttributedString(string: fullText)
        
        // 给指定词汇绑定自定义链接
        let linkRange = (fullText as NSString).range(of: "屏幕空间环境光遮蔽")
        let linkURL = "wiki://term/ssao"
        attributedString.addAttribute(.link, value: linkURL, range: linkRange)
        
        textView.attributedText = attributedString
    }

    // 拦截文本交互事件
    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        // 匹配自定义的内部链接scheme
        if URL.scheme == "wiki" {
            // 解析出链接携带的词条ID
            guard let termID = URL.host else { return false }
            // 调用自定义弹窗逻辑
            showWikiPopover(termID: termID, sourceRange: characterRange)
            // 返回false阻断系统默认打开行为
            return false
        }
        // 其他类型的外部链接(如http/https)可以保留系统默认打开逻辑
        return true
    }
    
    // 维基样式小型弹窗实现
    private func showWikiPopover(termID: String, sourceRange: NSRange) {
        // 这里根据termID获取对应的词条说明内容,可对接本地存储或网络请求
        let detailText = "屏幕空间环境光遮蔽(SSAO)是一种在屏幕空间计算场景阴影的渲染技术,能以较低性能开销提升画面真实感。"
        
        let popVC = UIViewController()
        popVC.modalPresentationStyle = .popover
        popVC.preferredContentSize = CGSize(width: 280, height: 180)
        
        // 给弹窗添加内容标签
        let contentLabel = UILabel(frame: CGRect(x: 12, y: 12, width: 256, height: 156))
        contentLabel.numberOfLines = 0
        contentLabel.text = detailText
        popVC.view.addSubview(contentLabel)
        
        // 把弹窗的箭头锚定到被点击的文字位置
        if let popPC = popVC.popoverPresentationController,
           let textPosition = textView.position(from: textView.beginningOfDocument, offset: sourceRange.location) {
            let anchorRect = textView.caretRect(for: textPosition)
            popPC.sourceView = textView
            popPC.sourceRect = anchorRect
            popPC.permittedArrowDirections = [.up, .down]
        }
        
        present(popVC, animated: true)
    }
}

常见踩坑提示

  • 默认的链接样式是蓝色带下划线,可以通过textView.linkTextAttributes统一调整,比如设置成App主题色、移除下划线,和整体UI保持一致
  • 弹窗锚点不需要手动硬编码坐标,通过UITextView的文本定位API可以精准拿到被点击文字的位置,对齐效果和维基百科的交互完全一致
  • 自定义链接和普通外部链接的逻辑互不干扰:代理方法里对不同scheme做分支判断即可,外部链接可以正常走系统打开流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 10:27:04