String.anotherIndex导致"致命错误:无法递增endIndex"

时间:2016-03-30 17:40:16

标签: ios swift

我尝试获取字符串的startIndex与另一个索引之间的距离,但在第一次循环迭代中得到以下错误。该代码实际上适用于大多数字符串,但有些代码会崩溃。

  

致命错误:无法递增endIndex

let content = NSMutableAttributedString(string: rawContent, attributes: attrs)

var startIndex = content.string.characters.startIndex

while true {
    let searchRange = startIndex..<rawContent.characters.endIndex
    if let range = rawContent.rangeOfString("\n", range: searchRange) {
        let index = rawContent.characters.startIndex.distanceTo(range.startIndex)
        startIndex = range.startIndex.advancedBy(1)

        rawContent.replaceRange(range, with: "*")
        content.addAttribute(
            NSForegroundColorAttributeName,
            value: UIColor.redColor(),
            range: NSMakeRange(index, 1))
    }
    else {
        break
    }
}

content.replaceCharactersInRange(NSMakeRange(0, content.length), withString: rawContent)

contentNSMutableAttributedString,当应用崩溃时,变量具有以下值:

range.startIndex: 164
content.string.characters.startIndex: 0
content.string.characters.endIndex: 437,
content.string.characters.count: 435

当我尝试计算距startIndex的距离并且anotherIndex小于字符串长度时,我不明白为什么错误消息会提到有关增加endIndex的信息。

2 个答案:

答案 0 :(得分:2)

错误的原因是您混合了Range<String.Index>NSRange API。第一个是Character s计数,第二个是UTF-16代码单位。如果您从:

开头
import Cocoa

let content = NSMutableAttributedString(string: "♥️♥️\n")

...然后你的代码进入一个无限循环(这是指@ Tapani的原始问题,我还没有检查他的变化后是否仍然如此;中心问题仍然是相同的)!这是因为:

NSString(string: "♥️♥️\n").length   // 5
"♥️♥️\n".characters.count           // 3

...这样你最终会用空格替换(部分)第二个心脏,留下新的线条,这样就可以让你进入循环。

避免这些问题的一种方法是采取以下措施:

let content = NSMutableAttributedString(string: "♥️♥️\n")

let newLinesPattern = try! NSRegularExpression(pattern: "\\n", options: [])

let length = (content.string as NSString).length
let fullRange = NSMakeRange(0, length)

let matches = newLinesPattern.matchesInString(content.string, options: [], range: fullRange)

for match in matches.reverse() {
    content.replaceCharactersInRange(match.range, withAttributedString: NSAttributedString(string: " "))
}

content.string // "♥️♥️ "

如果您将其复制并粘贴到游乐场并研究代码(例如,按住Alt键单击方法名称以弹出其API),您将看到此代码仅适用于NSRange指标。它也更安全,因为我们反向循环匹配的范围,所以你可以用不同长度的子串替换它们。此外,使用NSRegularExpression使这成为一种更通用的解决方案(另外,您可以存储模式并在其他地方重用它们)。最后,除了基于NSAttributedString replaceCharactersInRange的{​​{1}}之外,替换NSRange还可以让您更好地控制,即可以保留现有属性(从您的范围中获取它们)正在替换)或添加其他人......

答案 1 :(得分:0)

您的代码对我来说很好,但您应该进行错误检查。既然你正在搜索整个content.string,为什么还要增加设置搜索范围的复杂性?

这样的事情会更简单:

if let anotherIndex = content.string.rangeOfString("\n")
{
    let index = content.string.startIndex.distanceTo(anotherIndex.startIndex)
}