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

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

 func addingPercentEncoding(withAllowedCharacters: CharacterSet) -> String? 

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

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

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

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

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

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

Я опубликовал отчет об ошибке с 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) 

Основываясь на ответе Павла Кантрелла, небольшая демонстрация того, что также возможно, чтобы тот же метод также возвращал null в Objective-C, несмотря на то, что String и NSString были разными животными, когда дело доходит до кодировок:

 uint8_t bytes[2] = { 0xD8, 0x00 }; NSString *string = [[NSString alloc] initWithBytes:bytes length:2 encoding:NSUTF16BigEndianStringEncoding]; // \ud800 NSLog(@"%@", string); NSString *escapedString = [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLHostAllowedCharacterSet]; // (null) NSLog(@"%@", escapedString); 

Для удовольствия https://r12a.github.io/app-conversion/ будет иметь процентное значение, равное:

Ошибка% 20in% 20convertUTF162Char% 3A% 20low% 20surrogate% 20expected% 2C% 20b% 3D0% 21% 00

  • Что означает точка в R - личное предпочтение, соглашение об именовании или более?
  • Использование библиотеки FFMPEG с iPhone SDK для кодирования видео
  • Соглашения Java: использовать getters / setters внутри classа?
  • URL-код, кодирующий символ пробела: + или% 20?
  • В чем разница между кодировкой и кодировкой?
  • Кодировать NSString для XML / HTML
  • Какова правильная кодировка HTTP-запросов?
  • RStudio не выбирает кодировку, которую я говорю ей при чтении файла
  • Почему трассировка блоков стоит дорого?
  • Избавьтесь от уродливых утверждений
  • Base64 кодирует строку в VBScript
  • Давайте будем гением компьютера.