Fabio Poloni Fabio Poloni - 1 month ago 35
iOS Question

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?

Answer

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
    }
}
Comments