Почему возвращаемое значение String.addingPercentEncoding() необязательно?

Подпись метода String для процентного экранирования:

func addingPercentEncoding(withAllowedCharacters: CharacterSet)
    -> String?

(Это было stringByAddingPercentEncodingWithAllowedCharacters в Swift 2.)

Почему этот метод возвращает необязательный?

В документации говорится, что метод возвращает nil "если преобразование невозможно", но неясно, при каких обстоятельствах может произойти сбой преобразования:

  • Символы экранируются с использованием UTF-8, который является полной кодировкой Unicode. Любой допустимый символ Юникода может быть закодирован с использованием UTF-8 и, следовательно, может быть экранирован.

  • Я подумал, что, возможно, этот метод применил какую-то проверку здравомыслия для плохих взаимодействий между набором разрешенных символов и символами, используемыми для экранирования, но это не так: метод преуспевает независимо от того, установлен ли набор разрешенных chars содержит "%", а также успешно, если допустимый набор char пуст.

Как бы то ни было, необязательное возвращаемое значение, по-видимому, вызывает ненужную проверку ошибок.

Ответ 1

Я опубликовал отчет об ошибке с Apple об этом и услышал ответ - с очень полезным ответом, не менее!

Оказывается (к моему большому удивлению), что его можно успешно создать строки Swift, содержащие недопустимый Unicode в виде непарных суррогатных символов UTF-16. Такая строка может привести к сбою кодировки UTF-8. Вот какой код, который иллюстрирует это поведение:

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

// Returns nil:
str.addingPercentEncoding(withAllowedCharacters:
    CharacterSet.alphanumerics)