NSString.rangeOfString returns 非拉丁字符的异常结果
NSString.rangeOfString returns unusual result with non-latin characters
我需要获取字符串中两个单词的范围,例如:
ยัฟิแก ไฟหก
(这实际上是我在输入 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
时出现问题。
如何获得正确的范围(或在这种特定情况下,非重叠范围)?
删除 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)
Swift String
个字符描述 "extended grapheme clusters",并且 NSString
使用 UTF-16 代码点,因此字符串的长度不同
取决于您使用的表示形式。
比如第一个字符"ยั"
其实就是组合
"ย"
(U+0E22) 的变音符号 " ั"
(U+0E31)。
这算作一个 String
个字符,但算作两个 NSString
个字符。
因此,当您将单词替换为
空间。
最简单的解决方案是坚持一个,String
或 NSString
(如果可能的话)。由于您正在使用 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(" "))
我需要获取字符串中两个单词的范围,例如:
ยัฟิแก ไฟหก
(这实际上是我在输入 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
时出现问题。
如何获得正确的范围(或在这种特定情况下,非重叠范围)?
删除 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)
Swift String
个字符描述 "extended grapheme clusters",并且 NSString
使用 UTF-16 代码点,因此字符串的长度不同
取决于您使用的表示形式。
比如第一个字符"ยั"
其实就是组合
"ย"
(U+0E22) 的变音符号 " ั"
(U+0E31)。
这算作一个 String
个字符,但算作两个 NSString
个字符。
因此,当您将单词替换为
空间。
最简单的解决方案是坚持一个,String
或 NSString
(如果可能的话)。由于您正在使用 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(" "))