Search code examples
iosswiftnsattributedstring

NSAttributedString initialization throws NSRangeException


I wrote a simple extension to decode the html entities:

extension String {
    func htmlDecode() -> String {
        if let encodedData = self.data(using: String.Encoding.unicode) {
            let attributedString = try! NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode], documentAttributes: nil)
            return attributedString.string
        }
        return self
    }
}

Now it throws an error on the line if let attributedString …:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 2]'

And self is not nil or something, just a String like this:

self = (String) "...über 25'000 Franken..."

Where is this strange NSArray-exception coming from?


Solution

  • I just run over this error with a different error:

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance 0x60000024b790'

    And found a serious bug in this piece of code:

    I was passing String.Encoding.unicode - a Swift value - to an Objective-C method that crashed the app. After using String.Encoding.unicode.rawValue the crash disappeared:

    extension String {
        func htmlDecode() -> String {
            if let encodedData = self.data(using: String.Encoding.unicode) {
                if let attributedString = try? NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode.rawValue], documentAttributes: nil) {
                    return attributedString.string
                }
            }
            return self
        }
    }