我尝试获取字符串的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)
content
为NSMutableAttributedString
,当应用崩溃时,变量具有以下值:
range.startIndex: 164
content.string.characters.startIndex: 0
content.string.characters.endIndex: 437,
content.string.characters.count: 435
当我尝试计算距startIndex的距离并且anotherIndex
小于字符串长度时,我不明白为什么错误消息会提到有关增加endIndex的信息。
答案 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)
}