Swift项目中需要实现:一段文案默认最多显示3行,当超过三行时在末尾显示“更多”,当用户点击更多时,再展开显示所有文案:
期间遇到了一个类型转换的问题,在此记录说明一下:
代码语言:javascript复制let attributedString = NSMutableAttributedString(string: "这是一段可点击的文字,后面还有很多文案更多",
attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 16)])
guard let range = attributedString.string.range(of: "更多") else { // Range<String.Index>?
print("没有找到 更多 ")
return
}
// 在这里我遇到了一个Error:
// Cannot convert value of type 'Range<String.Index>?' to specified type 'NSRange?' (aka 'Optional<_NSRange>')
// 就是上面guard那句 产生的range的类型是:Range<String.Index>?
// 而下面的addAttribute那句 添加.link的value需要的类型是:NSRange?
// 系统无法自动将其转换,所以我需要手动转一下:
// 可以根据 'Range<String.Index>?' 和 '完整字符串' 创建 NSRange?, 如下:
let convertedRange = NSRange(range, in: attributedString.string) // NSRange?
attributedString.addAttribute(.link, value: "more://", range: convertedRange) // NSRange?
let textView: UITextView = UITextView(frame: CGRect(x: 30, y: 100, width: 300, height: 100))
textView.backgroundColor = .cyan
textView.isEditable = false
textView.isScrollEnabled = false
textView.delegate = self // 指定代理处理点击方法
textView.attributedText = attributedString
view.addSubview(textView)
然后在代理方法里截获URL,并根据项目需求进行相应的处理:
代码语言:javascript复制extension MOAttributedStringVC: UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if URL.absoluteString == "more://" {
print("click more")
return false
}
return true
}
}
参考:
iOS 富文本添加点击事件
Ranges in Swift explained with code examples