Я создаю простой просмотрщик кода / редактор поверх UITextView
, и поэтому я хочу раскрасить некоторые ключевые слова (переменные, функции и т. Д.), Чтобы их было легко просматривать, как в IDE. Я использую NSAttributedString
для этого и раскрашиваю в диапазоне, используя функции apply(...)
в цикле (см. Ниже). Однако, когда есть много слов для раскраски, он начинает становиться очень медленным и глушить клавиатуру (не столько на симуляторе, сколько на медленном устройстве на реальном устройстве). Я думал, что мог бы использовать многопоточность для решения этой проблемы, но когда я запускаю функцию apply в DispatchQueue.global().async {...}
, она вообще ничего не окрашивает. Обычно, если какой-либо вызов пользовательского интерфейса должен выполняться в главном потоке, он выведет сообщение об ошибке / сбое, и поэтому я могу найти, куда добавить DispatchQueue.main.sync {...}
, и я пробовал в разных местах, но он все еще не работает. Любые предложения о том, как я мог бы решить эту проблему?
Обновление звонка
func textViewDidChange(_ textView: UITextView) {
updateLineText()
}
Функция обновления
var wordToColor = [String:UIColor]()
func updateLineText() {
var newText = NSMutableAttributedString(string: content)
// some values are added to wordToColor here dynamically. This is quite fast and can be done asynchronously.
// when this is run asynchronously it doesn't color at all...
for word in wordToColor.keys {
newText = apply(string: newText, word: word)
}
textView.attributedText = newText
}
Применить функции
func apply (string: NSMutableAttributedString, word: String) -> NSMutableAttributedString {
let range = (string.string as NSString).range(of: word)
return apply(string: string, word: word, range: range, last: range)
}
func apply (string: NSMutableAttributedString, word: String, range: NSRange, last: NSRange) -> NSMutableAttributedString {
if range.location != NSNotFound {
if (rangeCheck(range: range)) {
string.addAttribute(NSAttributedStringKey.foregroundColor, value: wordToColor[word], range: range)
if (range.lowerBound != 0) {
let index0 = content.index(content.startIndex, offsetBy: range.lowerBound-1)
if (content[index0] == ".") {
string.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.purple, range: range)
}
}
}
let start = last.location + last.length
let end = string.string.count - start
let stringRange = NSRange(location: start, length: end)
let newRange = (string.string as NSString).range(of: word, options: [], range: stringRange)
apply(string: string, word: word, range: newRange, last: range)
}
return string
}