问题描述
extension UITextView {
func resolveHashTags() {
if self.text.isEmpty {
let emptyString = NSMutableAttributedString(string: " ",attributes: [NSAttributedString.Key.foregroundColor: UIColor.black,NSAttributedString.Key.font: self.font!])
self.attributedText = emptyString
self.textColor = .black
self.text = ""
return
}
let cursorRange = selectedRange
let nsText = Nsstring(string: self.text)
let words = nsText.components(separatedBy: CharacterSet(charactersIn: "@#ABCDEFGHIJKLMnopQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_").inverted).filter({!$0.isEmpty})
self.textColor = .black
let attrString = NSMutableAttributedString()
attrString.setAttributedString(self.attributedText)
attrString.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.black],range: nsText.range(of: self.text))
var anchor: Int = 0
for word in words {
// found a word that is prepended by a hashtag!
// homework for you: implement @mentions here too.
let matchRange:NSRange = nsText.range(of: word as String,range: NSRange(location: anchor,length: nsText.length - anchor))
anchor = matchRange.location + matchRange.length
if word.hasPrefix("#") {
// a range is the character position,followed by how many characters are in the word.
// we need this because we staple the "href" to this range.
// drop the hashtag
let stringifiedWord = word.dropFirst()
if let firstChar = stringifiedWord.unicodeScalars.first,NSCharacterSet.decimalDigits.contains(firstChar) {
// hashtag contains a number,like "#1"
// so don't make it clickable
} else {
// set a link for when the user clicks on this word.
// it's not enough to use the word "hash",but you need the url scheme Syntax "hash://"
// note: since it's a URL Now,the color is set to the project's tint color
attrString.addAttribute(NSAttributedString.Key.link,value: "hash:\(stringifiedWord)",range: matchRange)
}
} else if !word.hasPrefix("@") {
}
}
self.attributedText = attrString
self.selectedRange = cursorRange
}
}
所以这是我用来在 UITextView 中创建超链接的扩展。在 func textViewDidChange(_ textView: UITextView)
因此,在键入时是否有任何以 #
开头的单词。它将打开超链接并将颜色更改为蓝色。输入想要的单词后,如果按空格,它会返回黑色文本。这是预期的行为。
但是如果你清除文本并将你的课程移回像这样的标签词
仅保留指向该词的超链接的任何解决方案。在主题标签之后输入的任何内容都应该是普通文本
解决方法
我终于明白了。
func textView(_ textView: UITextView,shouldChangeTextIn range: NSRange,replacementText text: String) -> Bool {
var shouldReturn = true
let selectedRange = textView.selectedRange
let attributedText = NSMutableAttributedString(attributedString: textView.attributedText)
if !text.isEmpty && text != " " {
var userAttributes = [(NSAttributedString.Key,Any,NSRange)]()
attributedText.enumerateAttribute(.link,in: _NSRange(location: 0,length: textView.text.count),options: .longestEffectiveRangeNotRequired) { (value,range,stop) in
if let url = value as? String,url.hasPrefix("user:") {
userAttributes.append((.link,value!,range))
}
}
if let userLink = userAttributes.first(where: {$0.2.contains(range.location - 1)}) {
attributedText.replaceCharacters(in: range,with: NSAttributedString(string: text,attributes: [NSAttributedString.Key.link : userLink.1,NSAttributedString.Key.font : textView.font as Any]))
textView.attributedText = attributedText
shouldReturn = false
} else {
attributedText.replaceCharacters(in: range,attributes: [NSAttributedString.Key.font : textView.font as Any]))
textView.attributedText = attributedText
textDidChange?(textView)
shouldReturn = false
}
textView.selectedRange = _NSRange(location: selectedRange.location + text.count,length: 0)
textViewDidChange(textView)
}
return shouldReturn
}
通过这种方式,我可以控制更新单词之间的链接,并且之后不会扩展到新单词。