lidium
lidium

Reputation: 53

Range init?(NSRange, in: String) has been crashing

I got crash reports with these two exceptions (in the same line)

exception 1

Fatal Exception: NSInvalidArgumentException
-[__NSCFString characterAtIndex:]: Range or index out of bounds

exception 2

Fatal Exception: NSRangeException
*** -[NSBigMutableString characterAtIndex:]: Index 281474976710237 out of bounds; string length 481

exception 2 has a weird index number... It's close to 2^48

stack traces

Fatal Exception: NSInvalidArgumentException
0  CoreFoundation                 0x99288 __exceptionPreprocess
1  libobjc.A.dylib                0x16744 objc_exception_throw
2  CoreFoundation                 0x1a431c -[__NSCFString characterAtIndex:].cold.1
3  CoreFoundation                 0x1a4350 -[__NSCFString getCharacters:range:].cold.1
4  CoreFoundation                 0x24194 -[__NSCFString characterAtIndex:]
5  libswiftCore.dylib             0x228234 _StringGuts.foreignScalarAlign(_:)
6  libswiftCore.dylib             0x217058 _StringGuts.isOnUnicodeScalarBoundary(_:)
7  libswiftCore.dylib             0x20fb48 _StringGuts.isOnGraphemeClusterBoundary(_:)
8  libswiftCore.dylib             0x20f95c String.Index.init<A>(_:_genericWithin:)
9  libswiftCore.dylib             0x20fbf8 String.Index.init<A>(_:within:)
10 libswiftFoundation.dylib       0x34b58 Range<>.init(_:in:)
11 Desk                           0xc73ac4 String.word(at:) + 40 (String+WordAtRange.swift:40)
extension UITextView {
  var wordAtCaret: (word: String, range: NSRange)? {
    guard
      let caretRange = self.caretRange,
      let result = text.word(at: caretRange)
    else {
      return nil
    }
  }

 var caretRange: NSRange? {
    guard let selectedRange = self.selectedTextRange else { return nil }
    
    return NSRange(
      location: offset(from: beginningOfDocument, to: selectedRange.start),
      length: offset(from: selectedRange.start, to: selectedRange.end)
    )
  }
}

// String+WordAtRange.swift

extension String {
  func word(at nsrange: NSRange) -> (word: String, range: Range<String.Index>)? {
    let isValidRange = nsrange.location + nsrange.length <= self.utf16.count

    guard
      !isEmpty,
      isValidRange,
      let range = Range(nsrange, in: self), // crashes at this line
      let parts = self.wordParts(range)
    else {
      return nil
    }
}

Question 1: Why this initializer gets the crash even though it is a failable initializer?
When I tested in playground, nil is derived as expected.

Question 2: How can I solve these crashes?

Any help will be appreciated. Thanks!

Upvotes: 0

Views: 689

Answers (0)

Related Questions