3

我有下面的代码,在其中我传递了一个类型为的字符串,下面"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:: 越界'

正如我添加了printlns ,|r得到打印。请帮助,在此先感谢。

它不是这个问题的重复,因为|r正在被打印出来。

4

3 回答 3

1

我的猜测是错误发生在这一行:

attributedString.addAttribute("NSForegroundColorAttributeName", value: color, range: NSMakeRange(j, i-j))

让我们看看你的字符串 "Hello|r World|g" - 它有 15 个字符长。让我们看一下outer在找到第二个“|”时的迭代。strCopy 现在是“Hello World|g” - 13 个字符长,i = 11。程序找到一个“|” 后跟“r”并将 strCopy 更改为“Hello World|g” - 11 个字符长,仍然 i = 11。

在 inner for 中的“扫描”之后,我们最终得到 j = 7。

在这一行中,您从“Hello World”创建了一个可变字符串:

attributedString=NSMutableAttributedString(string: strCopy)

就像 strCopy 本身一样,它的长度等于 11。

现在,在最后一行中,您为 NSRangeMake(7, 4) 范围内的字符设置属性,这意味着它应用的最后一个字符将在索引 11 处。此字符串中的最后一个索引是 10,这就是你得到崩溃的原因.

编辑:为避免这种崩溃,您应该添加“i--;” 在每行后面加上 stringByReplacingOccurencesOfString。

您还应该做的另一件事(不会导致崩溃,但仍会使其故障)是更改内部 for 以便循环线如下所示:

for j = i + (string.length - strCopy.length); j>=0; j-- {

于 2015-04-14T11:26:04.647 回答
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
}
于 2015-04-14T16:31:51.660 回答
0

您的算法似乎取决于i指向最后处理的字符。每当你遇到|?模式,你最终用“”替换了两个特殊字符,有效地将复制字符串的大小减少了 2。

解决问题的最简单方法是i=i-2在每次调用后添加strCopy.stringByReplacingOccurrencesOfString....

i这对函数末尾的代码保持正确。

理想情况下,您可能需要考虑重组功能以将项目从原始版本移动到新版本,随时添加颜色等。这将节省所有向后搜索。

于 2015-04-14T12:49:52.537 回答