Swift 如何从 UITextView 获取链接范围

How to get links ranges from UITextView in Swift

我有一个聊天应用程序 UITextView 带有动态文本(来自服务器或由用户输入)。我需要检测所有类型的 link,而 UITextView 在检测 phone 数字、地址、hyperlink 和日历事件方面做得很好。 UITextView 不足之处在于样式,那里存在多个问题:

  1. 地址 link 未使用 tintColor 或来自 linkTextAttributes 属性 的颜色或使用 appearance() 代理着色。
  2. 默认情况下所有 link 都带有下划线。
  3. 一些 link 的颜色正确,但我看不出为什么某些 link 被省略的模式(看起来它可能与自动换行有关)。
  4. 设置自定义 underlineStyle 属性时,文本会消失。

所以我认为最好的办法是仍然使用 UITextView 来检测 link,然后创建我自己的属性字符串并按照我想要的方式设置所有样式。为此,我需要 link 的范围,但我找不到获取它们的方法。

我试过这个:

open func enumerateAttributes(in enumerationRange: NSRange, options opts: NSAttributedString.EnumerationOptions = [], using block: ([NSAttributedString.Key : Any], NSRange, UnsafeMutablePointer<ObjCBool>) -> Void)

但是从来没有任何 .link 元素,也没有任何下划线属性(如果我查找的话)。所以问题是,有没有办法以某种方式从 UITextView 获取 link 范围?或者也许有一种方法可以可靠地设置我缺少的 link 的样式?

要检测 Phone 号码、地址等,您实际上是在使用 NSDataDetector

这就是您在 InterfaceBuilder 中实际设置的内容:

然后:

let types: NSTextCheckingResult.CheckingType = [.address, .link, .phoneNumber, .date]
let detector = try? NSDataDetector(types: types.rawValue)
let matches = detector.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
matches.forEach {
    guard let range = Range([=10=].range, in: text) else { return }
    let sub = String(text[range])
    print(sub)
}