如何从 Swift 中的 UITextView 获取链接范围

Posted

技术标签:

【中文标题】如何从 Swift 中的 UITextView 获取链接范围【英文标题】:How to get links ranges from UITextView in Swift 【发布时间】:2020-12-10 13:51:04 【问题描述】:

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

    地址链接不使用tintColorlinkTextAttributes 属性的颜色或使用appearance() 代理着色。 默认情况下,所有链接都带有下划线。 某些链接的颜色正确,但我看不出某些链接被省略的模式(看起来可能与自动换行有关)。 当设置自定义underlineStyle 属性时,文本会消失。

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

我试过了:

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

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

【问题讨论】:

电话号码、地址等,使用数据检测器机制检测到。请参阅***.com/questions/41077174/… 枚举我认为您将能够使用match.range 然后;) @Larme 太棒了,这将使我忘记 UITextView 并自己设计所有内容。如果您在答案中写下此内容,我会接受。 【参考方案1】:

要检测电话号码、地址等,您实际上是在使用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($0.range, in: text) else  return 
    let sub = String(text[range])
    print(sub)

【讨论】:

我们需要日历或提醒应用的授权吗?如果 ios 在点击检测到的链接时显示动作控制器?这是默认行为。我没有使用任何 API 来创建事件或提醒。

以上是关于如何从 Swift 中的 UITextView 获取链接范围的主要内容,如果未能解决你的问题,请参考以下文章

我将如何(以编程方式)将 UITextView 的高度设置为其在 Swift 中的内容大小?

在 Swift 中的 UITextView 中添加占位符文本?

Swift 4 或 Swift 5 中的 UITextView 用户输入文本验证:限制 Swift 中的特定字符

在 Swift 中的 UITextView 上放置阴影

将rtf文件加载到Swift 2中的UITextView中

在 UITextView 中禁用光标和复制/粘贴(swift)