为什么 String.addingPercentEncoding() 的 return 值是可选的?
Why is the return value of String.addingPercentEncoding() optional?
String
百分比转义方法的签名是:
func addingPercentEncoding(withAllowedCharacters: CharacterSet)
-> String?
(这是 Swift 2 中的 stringByAddingPercentEncodingWithAllowedCharacters
。)
为什么这个方法 return 是可选的?
文档说方法 returns nil “如果转换不可能”,但不清楚在什么情况下转义转换会失败:
字符使用UTF-8转义,UTF-8是完整的Unicode编码。任何有效的 Unicode 字符都可以使用 UTF-8 编码,因此可以转义。
我想也许该方法对允许的字符集和用于转义的字符之间的不良交互应用了某种健全性检查,但事实并非如此:无论是否成功,该方法都会成功允许的字符集包含“%”,如果允许的字符集为空,也会成功。
就目前而言,非可选 return 值似乎在强制进行无意义的错误检查。
我就此向 Apple 提交了一份错误报告,并收到了回复 — 非常有帮助的回复,一点也不逊色!
事实证明(令我惊讶的是)可以成功创建 Swift 字符串,其中包含未配对 UTF-16 surrogate chars 形式的无效 Unicode。这样的字符串会导致 UTF-8 编码失败。下面是一些说明此行为的代码:
// Succeeds (wat?!):
let str = String(
bytes: [0xD8, 0x00] as [UInt8],
encoding: .utf16BigEndian)!
// Returns nil:
str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
基于 Paul Cantrell 的回答,小规模的演示表明同样的方法也可以在 Objective-C 中 return null,尽管 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/ 将百分比转义为:
Error%20in%20convertUTF162Char%3A%20low%20surrogate%20expected%2C%20b%3D0%21%00
String
百分比转义方法的签名是:
func addingPercentEncoding(withAllowedCharacters: CharacterSet)
-> String?
(这是 Swift 2 中的 stringByAddingPercentEncodingWithAllowedCharacters
。)
为什么这个方法 return 是可选的?
文档说方法 returns nil “如果转换不可能”,但不清楚在什么情况下转义转换会失败:
字符使用UTF-8转义,UTF-8是完整的Unicode编码。任何有效的 Unicode 字符都可以使用 UTF-8 编码,因此可以转义。
我想也许该方法对允许的字符集和用于转义的字符之间的不良交互应用了某种健全性检查,但事实并非如此:无论是否成功,该方法都会成功允许的字符集包含“%”,如果允许的字符集为空,也会成功。
就目前而言,非可选 return 值似乎在强制进行无意义的错误检查。
我就此向 Apple 提交了一份错误报告,并收到了回复 — 非常有帮助的回复,一点也不逊色!
事实证明(令我惊讶的是)可以成功创建 Swift 字符串,其中包含未配对 UTF-16 surrogate chars 形式的无效 Unicode。这样的字符串会导致 UTF-8 编码失败。下面是一些说明此行为的代码:
// Succeeds (wat?!):
let str = String(
bytes: [0xD8, 0x00] as [UInt8],
encoding: .utf16BigEndian)!
// Returns nil:
str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
基于 Paul Cantrell 的回答,小规模的演示表明同样的方法也可以在 Objective-C 中 return null,尽管 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/ 将百分比转义为:
Error%20in%20convertUTF162Char%3A%20low%20surrogate%20expected%2C%20b%3D0%21%00