Я написал этот mid
метод в Extension
.
func mid(fromIndex: Int, toIndex: Int) -> String {
var _fromIndex = 0
if( fromIndex >= self.count ) {
return ""
}
else if( fromIndex > 0 ){
_fromIndex = fromIndex
}
var _toIndex = 0
if( toIndex >= self.count ) {
_toIndex = self.count - 1
}
else if( toIndex > 0 ){
_toIndex = toIndex
}
if( _fromIndex > _toIndex ){
return ""
}
return String(self[self.index(self.startIndex, offsetBy: _fromIndex)...self.index(self.startIndex, offsetBy: _toIndex)])
}
и использую этот метод для извлечения удаленной пользователем строки.
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
defer{
if text.isEmpty {
let deletedText = textView.attributedText.string.mid(fromIndex: range.lowerBound, toIndex: range.upperBound)
}
}
}
Но иногда это вызывает исключение.
Fatal Exception: NSRangeException
*** -[NSBigMutableString characterAtIndex:]: Index 672 out of bounds; string length 672
specialized String.subscript.getter
Я уже проверяю размер строки перед использованием String.subscript.getter
.
if( toIndex >= self.count ) {
_toIndex = self.count - 1
}
И текстовая операция должна выполняться в основном потоке. Почему я все еще получаю это исключение? Неужели я неправильно понял индекс строки в Swift?
UPDATE1
Согласно ответу @ Wattholm. Я использую этот способ, чтобы получить текст с NSRange
из UITextView
.
let contents: String = textView.text
if let _range = Range(range, in: contents) {
let deletedText = String(contents[_range])
}
else {
logHelper.w("Failed to get deletedText from NSRange, try UITextRange.")
if let startPosition = textView.position(from: textView.beginningOfDocument, offset: range.location),
let endPosition = textView.position(from: startPosition, offset: range.length),
let textRange = textView.textRange(from: startPosition, to: endPosition),
let deletedText = textView.text(in: textRange) {
// do something with deletedText
}
else {
logHelper.w("Failed to get deletedText from UITextRange, try NSString.")
let deletedText = (contents as NSString).mid(fromIndex: range.lowerBound, toIndex: range.upperBound)
}
}
Но он все равно попадает во второй else
и выбрасывает NSRangeException
. Это означает, что длина и индекс по-прежнему не соответствуют друг другу.
UPDATE2
Пытался использовать NSString.substring
, но все еще продолжаю получать это исключение.
let deletedText = (contents as NSString).substring(with: range)
Возможно, есть ошибка в UITextView?