了解Swift的CharacterSet

tldr:单击 此处 查看 CharacterSet.decimalDigits 所有 CharacterSet.decimalDigits

您是否曾经需要检查过字符串是否仅由数字组成? 标点符号或非字母数字字符的存在如何? 一个人可以使用多种方法,从Formatter类之一到NSScanner甚至是NSPredicate ,但是您发现的最可能的代码片段涉及到使用反向的CharacterSet

简而言之, CharacterSet是一个由Objective-C桥接的Swift类,它代表一组Unicode字符。 它的Objective-C对应物NSCharacterSet本身是免费的,与Core Foundation的CFCharacterSet桥接。 CFCharacterSet用C编写,相当古老,至少可以追溯到Mac CFCharacterSet的主要思想是提供一种支持Unicode的数据结构,以帮助有效地搜索Unicode字符串。 NSStringNSScanner内部使用NSCharacterSet进行字符串搜索操作。

可以将CharacterSet初始化为空集,也可以将其初始化为字符串,字节或文件内容中存在的一组字符。 它带有许多方便的预定义集合(例如URL查询片段中允许的字符或字母数字字符),甚至还允许集合代数(例如并集,交集和异或)。

使用CharacterSet的预定义集合之一感觉很方便:

请注意,四个8位和两个16位都加起来为32位。 这完全是设计使然:UTF32是固定宽度格式,UTF8和UTF16可以轻松装入其中,而无需进行任何额外工作。 所有UTF32字符都包含32位,即使不是必需的。 这使格式无效,但是有一个好处 :它非常适合搜索,因为您可以遍历第32位以获得下一个字符,而不用解码每个字节来解码该字符的代码点宽度。 这正是NSCharacterSet.characterIsMember(UTF8 or UTF16 or UTF32)内部调用仅接受UTF32字符的longCharacterIsMember(UTF32)的原因NSCharacterSet.characterIsMember(UTF8 or UTF16 or UTF32)

CharacterSet搜索字符成员资格的最佳方法是获取该CharacterSet的UTF32代码点,并将其传递给NSCharacterSetlongCharacterIsMember() 。 看起来像这样:


以下是将字符的代码点值转换为UTF8二进制文件的方法:在上表中的所有x s中填充字符的二进制值。

要确定需要多少字节,请考虑二进制字符编码的长度。 1字节的UTF8仅可容纳7位(表中仅7 x s)。 一个2字节的UTF8可以容纳11位。 3字节可容纳16位,而4字节UTF8可容纳21位。

对于“€”字符(U + 20AC 10 0000 1010 1100 ),我们至少需要14位,这意味着它将需要3个字节的结构,可以容纳12至16位。 填充到UTF8结构中的二进制数字如下所示: 1110 0010 10 000010 10 101100 (代码点为bold )。

请注意,如果您删除了非粗体的二进制数字,您将获得“€”字符的原始二进制!

3字节长的UTF8字符中的第一个字节始终以1110开头。 这就是UTF8解码器如何知道后面的字节数属于数据流中相同字符的方式。

³参见CFCharacterSet.c的第1655行

⁴我建议在任何生产应用程序或任何应用程序中使用此代码 提供的NSCharacterSet扩展名仅用于教育目的。 代码很慢,并且一些预定义的集合很大 (例如, .alphanumerics集合包含24,146个字符)。

⁵再一次,我不建议在生产环境中使用NSCharacterSet扩展。