我有以下代码,其中我传递了一个类型为"Hello|r World|g"
的字符串,以下函数将其转换为attributedString
,"Hello"
为red
颜色和"World"
颜色为green
。当我传递数组中的每个字符串时,我使用了这个。该函数仅对文本进行着色,直到它找到一个特殊字符,如结束时的条件所示,然后为文本着色。
代码:
func formatAttributedString(string:String)->NSMutableAttributedString {
var strCopy=string as NSString
var color:UIColor=UIColor()
var attributedString:NSMutableAttributedString!
for var i:Int=0;i<strCopy.length-2;i++ {
if (string[i] == "|") {
println("|")
var j:Int
if string[i+1] == "r" {
color=UIColor(red: 249, green: 39, blue: 14, alpha: 1)
strCopy = strCopy.stringByReplacingOccurrencesOfString("|r", withString: "", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, i + 2))
println("r")
}
else if string[i+1] == "v" {
color=UIColor(red: 161, green: 153, blue: 249, alpha: 1)
strCopy = strCopy.stringByReplacingOccurrencesOfString("|v", withString: "", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, i + 2))
println("v")
}
else if string[i+1] == "y" {
color=UIColor(red: 235, green: 223, blue: 145, alpha: 1)
strCopy = strCopy.stringByReplacingOccurrencesOfString("|y", withString: "", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, i + 2))
println("y")
}
else if string[i+1] == "g" {
color=UIColor(red: 174, green: 227, blue: 79, alpha: 1)
strCopy = strCopy.stringByReplacingOccurrencesOfString("|y", withString: "", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, i + 2))
println("g")
}
else if string[i+1] == "b" {
color=UIColor(red: 107, green: 224, blue: 240, alpha: 1)
strCopy = strCopy.stringByReplacingOccurrencesOfString("|b", withString: "", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, i + 2))
println("b")
}
for j=i; j>=0;j-- {
if string[j] == " " || string[j] == "/" || string[j] == "." || string[j] == "\"" || string[j] == "\n" || string[j] == "<" || string[j] == "\t" || string[j] == "("{
println("/")
break
}
}
attributedString=NSMutableAttributedString(string: strCopy)
attributedString.addAttribute("NSForegroundColorAttributeName", value: color, range: NSMakeRange(j, i-j))
}
}
我收到以下错误:
'NSMutableRLEArray objectAtIndex:effectiveRange :: out of bounds'
当我添加println
时,|
和r
会被打印出来。
请帮助,提前致谢。
由于|
并且r
正在打印,因此this question不重复。
答案 0 :(得分:1)
我的猜测是错误发生在这一行:
attributedString.addAttribute("NSForegroundColorAttributeName", value: color, range: NSMakeRange(j, i-j))
让我们看一下你的字符串“Hello | r World | g” - 它的长度为15个字符。 让我们看看外部的迭代,当它找到第二个“|”时。 strCopy现在是“Hello World | g” - 长度为13个字符,i = 11。 程序找到“|”接着是“r”并将strCopy更改为“Hello World | g” - 长度为11个字符且仍为i = 11.
在内部的“扫描”之后,我们以j = 7结束。
在这一行中,您可以从“Hello World”创建一个可变字符串:
attributedString=NSMutableAttributedString(string: strCopy)
就像strCopy本身一样,长度等于11。
现在,在最后一行中,为NSRangeMake(7,4)中的字符设置属性,这意味着它应用的最后一个字符将是索引11.此字符串中的最后一个索引是10,这就是为什么你得到了崩溃。
编辑: 为了避免这种崩溃你应该添加“i--;”在每行之后使用stringByReplacingOccurencesOfString。
你还应该做的另一件事(它不会导致崩溃,但仍会使其失灵,是改变内部,以便循环线看起来像这样:
for j = i + (string.length - strCopy.length); j>=0; j-- {
答案 1 :(得分:1)
我尝试使用Swift的匿名元组和更高阶函数来实现与另一个实现的函数签名。我这样做是为了锻炼自己,最后还是最好分享。
func formatAttributedString(string: String) -> NSMutableAttributedString {
// create a mapping between the attribute token and the corresponding UIColor
let colors = [
"|r": UIColor(red: 249/255, green: 39/255, blue: 14/255, alpha: 1.0),
"|v": UIColor(red: 161/255, green: 153/255, blue: 249/255, alpha: 1.0),
"|y": UIColor(red: 235/255, green: 223/255, blue: 145/255, alpha: 1.0),
"|g": UIColor(red: 174/255, green: 227/255, blue: 79/255, alpha: 1.0),
"|b": UIColor(red: 107/255, green: 224/255, blue: 240/255, alpha: 1.0)]
// split argument into an array of (String, UIColor) tuples
// default the array to the entire argument string with a black color
var substrings = [(string, UIColor.blackColor())]
for (token, color) in colors {
substrings = substrings.flatMap {
var substrings = $0.0.componentsSeparatedByString(token)
let tail = (substrings.removeLast(), $0.1) // tuple for trailing string at old color
var result = substrings.map{($0, color)} // array of tuples for strings at new color
result.append(tail)
return result
}
}
// because we default the original string to black, there may be an empty string tuple at the end
substrings = substrings.filter{(string, _) in return !string.isEmpty}
// convert array of (String, UIColor) tuples into a single attributed string
var result = reduce(substrings, NSMutableAttributedString(string: "")) {
var string = NSAttributedString(string: $1.0, attributes: [NSForegroundColorAttributeName: $1.1])
$0.appendAttributedString(string)
return $0
}
return result
}
答案 2 :(得分:0)
您的算法似乎依赖于i
指向最后处理的字符。每当遇到|?模式,你最终用“”替换两个特殊字符,有效地将复制字符串大小减少2。
解决问题的最简单方法是在每次调用i=i-2
后添加strCopy.stringByReplacingOccurrencesOfString...
。
这使得i
对函数末尾的代码保持正确。
理想情况下,您可能需要考虑重构功能,将项目从原始版本移动到新版本,添加颜色等。这将保存所有向后搜索。