swiftcocoaunicodeutf-8url-encoding

Why is the return value of String.addingPercentEncoding() optional?


The signature of the String method for percent-escaping is:

func addingPercentEncoding(withAllowedCharacters: CharacterSet)
    -> String?

(This was stringByAddingPercentEncodingWithAllowedCharacters in Swift 2.)

Why does this method return an optional?

The documentation says that the method returns nil “if the transformation is not possible,” but it's unclear under what circumstances the escaping transformation could fail:

As it stands, the non-optional return value appear to be forcing a nonsensical error check.


Solution

  • I filed a bug report with Apple about this, and heard back — with a very helpful response, no less!

    Turns out (much to my surprise) that it’s possible to successfully create Swift strings that contain invalid Unicode in the form of unpaired UTF-16 surrogate chars. Such a string can cause UTF-8 encoding to fail. Here’s some code that illustrates this behavior:

    // Succeeds (wat?!):
    let str = String(
        bytes: [0xD8, 0x00] as [UInt8],
        encoding: .utf16BigEndian)!
    
    // Returns nil:
    str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)