56

Following code was perfectly worked with old swift. This is an extension of String

func stringByConvertingHTML() -> String {
    let newString = replacingOccurrences(of: "\n", with: "<br>")
    if let encodedData = newString.data(using: String.Encoding.utf8) {
        let attributedOptions : [String: AnyObject] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType as AnyObject,
            NSCharacterEncodingDocumentAttribute: String.Encoding.utf8 as AnyObject
        ]
        do {
            let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil) //Crash here
            return attributedString.string
        } catch {
            return self
        }
    }
    return self
}

But in swift 3 it crashes saying

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

Anyone please suggest me what need to do?

Tapas Pal
  • 7,073
  • 8
  • 39
  • 86

3 Answers3

96

I ran into the same problem:

let attributedOptions : [String: AnyObject] = [
            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType as AnyObject,
            NSCharacterEncodingDocumentAttribute: String.Encoding.utf8 as AnyObject
        ]

Here the String.Encoding.utf8 the type check fails. Use NSNumber(value: String.Encoding.utf8.rawValue)

Forge
  • 6,538
  • 6
  • 44
  • 64
Sachin Vas
  • 1,757
  • 12
  • 16
  • 14
    Thanks it's working fine. But it'll be `NSNumber(value: String.Encoding.utf8.rawValue)` – Tapas Pal Sep 22 '16 at 17:18
  • Lifesaver! (PS: Also needed the NSNumber( .. ) to work, could you plz update the answer to include that instead?) – Marchy Oct 27 '16 at 16:39
  • 7
    You should just need `String.Encoding.utf8.rawValue`, as Swift will automatically convert `Int`s and `UInt`s into `NSNumber`s when a Swift dictionary is passed to a function expecting an `NSDictionary`. Although that will require having the swift dictionary being a `[String: Any]` array. See also [this](https://developer.apple.com/swift/blog/?id=39) Swift blog entry. – MaddTheSane Feb 23 '17 at 07:33
  • Sometimes I am getting NSRangeException, any solution to this – Neha Feb 06 '18 at 06:15
  • Weird! But it is true, enumerations should be sent as rawValue. I assume it will be fixed in future versions. – Hola Soy Edu Feliz Navidad Apr 12 '18 at 15:05
48

In Swift3 no cast to AnyObject is needed anymore and also no NSNumber.

let attrs: [String: Any] = [
            NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue
        ]
zidanex
  • 524
  • 3
  • 5
8

This post saved my day. After migrating to Swift 3, the little change String.Encoding.utf8 to String.Encoding.utf8.rawValue fixed the trap reported here.

Orignal line:

...
    options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,
              NSCharacterEncodingDocumentAttribute: String.Encoding.utf8],
...

changed to

options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,
          NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue],

add the .rawValue to the end...

mfaani
  • 33,269
  • 19
  • 164
  • 293
  • Would never have guessed from error note that solution was to add .rawValue at the end. Great many thanx! – JOM Oct 03 '18 at 04:18