String.Index(_:within :)初始化程序崩溃

时间:2015-08-10 07:28:09

标签: string swift

我最近一直在用String索引搞砸了一些事情,我很难搞清楚事情,但仍有些事情让我烦恼。

我正在尝试使用init(_:within:)类型为String.Index的方法。当我在字符串的边界内使用utf16index时它很好用,但是当它在外面它时会崩溃:

  

致命错误:此UnicodeScalar视图的String.UTF16Index无效

现在我得到了文档中所述的函数要求:

/// - Requires: `utf16Index` is an element of
///   `characters.utf16.indices`.

实际问题:当init是一个可用的初始化程序时,我没有得到的是为什么会崩溃?它不应该返回nil

我可能会制作一个方法来检查索引是否可以在字符串中,但对我来说听起来仍然很奇怪。

1 个答案:

答案 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。这违反了要求并导致运行时 例外。
  • 给定的utf16Indexcharacters.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索引013对应有效的字符位置, 但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()

的3参数形式
let i16 = advance(str.utf16.startIndex, offset, str.utf16.endIndex)
相关问题