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

如何让UIAlertController文本消息中的HTML链接可点击?

解决UIAlertController富文本链接不可点击的通用方案

这个问题我之前也碰到过!UIAlertController默认确实不会让富文本里的链接可点击,哪怕你已经把HTML转成了正确的富文本格式。既然你的文本来自API没法提前处理字符串,那咱们可以用下面这个通用方案来实现:

核心思路

UIAlertController的message标签默认禁用了用户交互,而且不会自动响应链接点击。所以要解决这个问题,我们需要做两件事:

  1. 找到Alert里显示富文本的UILabel,开启它的用户交互
  2. 添加点击手势,根据点击位置解析对应的链接并打开

具体实现

你可以给UIAlertController写个扩展,把所有逻辑封装起来,以后用起来特别方便:

import UIKit

extension UIAlertController {
    // 启用Alert中富文本链接的点击交互
    func enableInteractiveLinks() {
        // 递归遍历所有子视图,找到包含链接的UILabel
        func findLinkContainingLabels(in view: UIView) -> [UILabel] {
            var targetLabels = [UILabel]()
            for subview in view.subviews {
                if let label = subview as? UILabel, let attrText = label.attributedText {
                    // 检查这个Label的富文本是否包含链接属性
                    var hasLink = false
                    attrText.enumerateAttribute(.link, in: NSRange(location: 0, length: attrText.length), options: []) { value, _, stop in
                        if value != nil {
                            hasLink = true
                            stop.pointee = true
                        }
                    }
                    if hasLink {
                        targetLabels.append(label)
                    }
                }
                // 递归查找子视图
                targetLabels += findLinkContainingLabels(in: subview)
            }
            return targetLabels
        }
        
        // 找到所有需要处理的Label
        let linkLabels = findLinkContainingLabels(in: self.view)
        for label in linkLabels {
            label.isUserInteractionEnabled = true
            // 添加点击手势
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleLinkTap(_:)))
            label.addGestureRecognizer(tapGesture)
        }
    }
    
    // 处理链接点击事件
    @objc private func handleLinkTap(_ gesture: UITapGestureRecognizer) {
        guard let label = gesture.view as? UILabel, let attrText = label.attributedText else { return }
        
        // 计算点击位置对应的字符索引
        let tapLocation = gesture.location(in: label)
        let textContainer = NSTextContainer(size: label.bounds.size)
        textContainer.lineFragmentPadding = 0
        textContainer.maximumNumberOfLines = label.numberOfLines
        textContainer.lineBreakMode = label.lineBreakMode
        
        let layoutManager = NSLayoutManager()
        layoutManager.addTextContainer(textContainer)
        
        let textStorage = NSTextStorage(attributedString: attrText)
        textStorage.addLayoutManager(layoutManager)
        
        let characterIndex = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
        
        // 获取对应位置的链接并打开
        guard characterIndex < attrText.length else { return }
        let attributes = attrText.attributes(at: characterIndex, effectiveRange: nil)
        if let targetURL = attributes[.link] as? URL {
            UIApplication.shared.open(targetURL)
        }
    }
}

使用方式

按照你原来的流程,把API返回的HTML转成富文本,然后设置给Alert,最后调用扩展方法即可:

// 1. 从API获取HTML字符串
let apiHtmlString = "<p>这是来自API的文本,包含<a href='https://example.com'>可点击链接</a></p>"

// 2. 转成富文本(用你现有的html2AttributedString扩展)
guard let attributedMessage = apiHtmlString.html2AttributedString else {
    // 处理转换失败的情况
    return
}

// 3. 创建AlertController
let alert = UIAlertController(title: "提示", message: nil, preferredStyle: .alert)
// 通过KVC设置富文本message(iOS10+支持)
alert.setValue(attributedMessage, forKey: "attributedMessage")

// 4. 启用链接点击交互
alert.enableInteractiveLinks()

// 5. 添加按钮并present
alert.addAction(UIAlertAction(title: "确定", style: .default))
present(alert, animated: true)

注意事项

  • 确保你的html2AttributedString扩展正确设置了NSLinkAttributeName属性,这样我们才能识别到链接
  • 如果链接是HTTP协议,需要在Info.plist中配置NSAppTransportSecurity允许非HTTPS请求(或者针对特定域名配置)
  • 这个方法兼容iOS10及以上版本,因为attributedMessage的KVC设置是iOS10开始支持的

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:49:26