NSString.rangeOfString返回非拉丁字符的异常结果

时间:2016-09-06 18:25:18

标签: swift cocoa nsstring nsrange

我需要在字符串中获取两个单词的范围,例如:

ยัฟิแก ไฟหก

(这就是我输入PYABCD WASD) - 这是一个非感性测试,因为我不会说泰语。

//Find all the ranges of each word
var words:  [String]    = []
var ranges: [NSRange]   = []

//Convert to nsstring first because otherwise you get stuck with Ranges and Strings.
let nstext = backgroundTextField.stringValue as NSString //contains "ยัฟิแก ไฟหก"
words  = nstext.componentsSeparatedByString(" ")
var nstextLessWordsWeHaveRangesFor = nstext //if you have two identical words this prevents just getting the first word's range

for word in words
        {

            let range:NSRange = nstextLessWordsWeHaveRangesFor.rangeOfString(word)
            Swift.print(range)
            ranges.append(range)

            //create a string the same length as word
            var fillerString:String = ""

            for i in 0..<word.characters.count{
            //for var i=0;i<word.characters.count;i += 1{
                Swift.print("i: \(i)")
               fillerString = fillerString.stringByAppendingString(" ")
            }

            //remove duplicate words / letters so that we get correct range each time. 
            if range.length <= nstextLessWordsWeHaveRangesFor.length
            {
                nstextLessWordsWeHaveRangesFor = nstextLessWordsWeHaveRangesFor.stringByReplacingCharactersInRange(range, withString: fillerString)
            }             
        }

输出:

(0,6)
(5,4)

这些范围重叠。

由于范围不一致,这会导致我尝试使用NSLayoutManager.enumerateEnclosingRectsForGlyphRange的问题。

如何获得正确的范围(或在此特定情况下,非重叠范围)?

2 个答案:

答案 0 :(得分:3)

Swift String个字符描述&#34;扩展的字形集群&#34;和NSString 使用UTF-16代码点,因此字符串的长度不同 取决于您使用的表示形式。

例如,第一个字符"ยั"实际上就是组合 具有变音标记"ย"(U + 0E31)的" ั"(U + 0E22)。 这计为一个String个字符,但为两个NSString个字符。 因此,当您用单词替换时,索引会发生变化 空格。

最简单的解决方案是坚持使用StringNSString (如果可能的话)。由于您正在使用NSString,正在更改

 for i in 0..<word.characters.count {

for i in 0..<range.length {

应该解决问题。填充字符串的创建 可以简化为

//create a string the same length as word
let fillerString = String(count: range.length, repeatedValue: Character(" "))

答案 1 :(得分:1)

删除nstextLessWordsWeHaveRangesFor解决了问题(从range.length <= nstextLessWordsWeHaveRangesFor.length开始在底部)。修改该变量会改变范围并产生意外的输出。删除重复的单词删除时的结果如下:

var words: [String] = []

let nstext = "ยัฟิแก ไฟหก" as NSString
words = nstext.componentsSeparatedByString(" ")

for word in words {
    let range = nstext.rangeOfString(word)
    print(range)
}

输出为:(0,6)(7,4)