UITextView
中有一个属性文本,当用户点击文本的某个位置时(不选择文本,只是将闪烁的光标放在其他位置),光标周围的整个句子会改变颜色。
private func setFocus(boundarySymbols: CharacterSet) {
let mutableString = NSMutableAttributedString(attributedString: noteTextView.attributedText)
mutableString.beginEditing()
unfocusWholeText(mutableString: mutableString)
let selectedRange = noteTextView.selectedRange
guard let caretPosition = findCaretPosition() else { return }
guard let focusRange = findRangeToFocus(in: noteTextView.text, around: caretPosition, of: boundarySymbols) else { return }
text.addAttribute(NSForegroundColorAttributeName, value: ThemeManager.theme.note.text, range: focusRange)
mutableString.endEditing()
noteTextView.attributedText = mutableString
noteTextView.selectedRange = selectedRange
}
当我在shouldChangeTextIn
的{{1}}方法中调用此函数时效果很好,但只有在用户输入时才有效,我想在用户只更改选择时调用此函数{{ 1}}似乎很合适。
当我将修改后的referencedString分配给UITextViewDelegate
时,它将光标移动到文本的末尾(用保存光标位置修复它并在所有更改后再次设置它)。但问题是这两件事都在移动光标并再次调用textViewDidChangeSelection
所以发生无限循环(UITextView
正在调用我的textViewDidChangeSelection
,这会修改光标位置,因此调用{{1再次)。
我可以在不创建NSMutableAttributedString的情况下更改attributesString的属性(基本上只是颜色),并再次将其重新分配给UITextView.attributedText,以省略将光标移动到文本的末尾并返回吗?
或许有一种方法可以某种方式关闭它不应该移动那个光标或者让它暂时不调用代理?
答案 0 :(得分:1)
经过长时间的战斗后,我最终得到了一些简单的解决方法,这在早些时候没有出现在我的脑海中。
在放置在setFocus
函数中的textViewDidChangeSelection
中,我将UITextViewDelegate
设置为nil
,在更改颜色和设置光标后,我再次分配代理。不是一个干净的解决方案,但至少有效。
答案 1 :(得分:0)
我为我的一个项目写了一个UITextField
扩展名,可以让你这样做:
extension UITextField {
enum ShouldChangeCursor {
case incrementCursor
case preserveCursor
}
func preserveCursorPosition(withChanges mutatingFunction: (UITextPosition?) -> (ShouldChangeCursor)) {
//save the cursor positon
var cursorPosition: UITextPosition? = nil
if let selectedRange = self.selectedTextRange {
let offset = self.offset(from: self.beginningOfDocument, to: selectedRange.start)
cursorPosition = self.position(from: self.beginningOfDocument, offset: offset)
}
//make mutaing changes that may reset the cursor position
let shouldChangeCursor = mutatingFunction(cursorPosition)
//restore the cursor
if var cursorPosition = cursorPosition {
if shouldChangeCursor == .incrementCursor {
cursorPosition = self.position(from: cursorPosition, offset: 1) ?? cursorPosition
}
if let range = self.textRange(from: cursorPosition, to: cursorPosition) {
self.selectedTextRange = range
}
}
}
}
您可以使用它来更新属性文本而不更改光标位置:
textField.preserveCursorPosition(withChanges: { _ in
textField.attributedText = ...
return .preserveCursor
})