我最近一直在用String
索引搞砸了一些事情,我很难搞清楚事情,但仍有些事情让我烦恼。
我正在尝试使用init(_:within:)
类型为String.Index
的方法。当我在字符串的边界内使用utf16index
时它很好用,但是当它在外面它时会崩溃:
致命错误:此UnicodeScalar视图的String.UTF16Index无效
现在我得到了文档中所述的函数要求:
/// - Requires: `utf16Index` is an element of
/// `characters.utf16.indices`.
实际问题:当init
是一个可用的初始化程序时,我没有得到的是为什么会崩溃?它不应该返回nil
?
我可能会制作一个方法来检查索引是否可以在字符串中,但对我来说听起来仍然很奇怪。
答案 0 :(得分:2)
该方法的完整标题文档是
extension String.CharacterView.Index {
// ...
public init?(_ unicodeScalarIndex: UnicodeScalarIndex, within characters: String)
/// Construct the position in `characters` that corresponds exactly to
/// `utf16Index`. If no such position exists, the result is `nil`.
///
/// - Requires: `utf16Index` is an element of
/// `characters.utf16.indices`.
public init?(_ utf16Index: UTF16Index, within characters: String)
// ...
}
因此有两种不同的失败原因:
utf16Index
超出了有效索引的范围
characters.utf16
。这违反了要求并导致运行时
例外。 utf16Index
是characters.utf16
的有效索引,但是
没有与该索引对应的字符位置。
在这种情况下,该方法返回nil
。作为一个例子,考虑字符串" ab"。它由三个字符组成, 但是四个UTF-16代码单元:
let str = "ab"
str.characters.count // 3
str.utf16.count // 4
Array(str.utf16) // [97, 55357, 56447, 98]
(另见Strings in Swift 2 在Swift博客中。)
UTF-16索引0
,1
,3
对应有效的字符位置,
但2
没有:
String.Index(str.utf16.startIndex, within: str) // 0
String.Index(str.utf16.startIndex + 1, within: str) // 1
String.Index(str.utf16.startIndex + 2, within: str) // nil
String.Index(str.utf16.startIndex + 3, within: str) // 3
实际上"一个结束了" position(utf16.endIndex
)也是有效的(这对我来说并不明显
从标题文档中),在这种情况下返回characters.endIndex
:
String.Index(str.utf16.startIndex + 4, within: str) // 4
str.characters.endIndex // 4
但endIndex
以外的所有内容都会导致运行时异常:
String.Index(str.utf16.startIndex + 5, within: str) // EXC_BAD_INSTRUCTION
要计算有效范围内的UTF-16索引,可以使用
advance()
let i16 = advance(str.utf16.startIndex, offset, str.utf16.endIndex)