【问题标题】:NSString.rangeOfString returns unusual result with non-latin charactersNSString.rangeOfString 返回非拉丁字符的异常结果
【发布时间】:2017-01-14 07:08:43
【问题描述】:

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

ยัฟิแก ไฟหก

(这实际上是我在输入 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 时出现问题,因为范围不一致。

我怎样才能获得正确的范围(或者在这种特定情况下,非重叠范围)?

【问题讨论】:

  • 你的代码中只有一个打印语句,如何得到两个输出行?
  • 这真的是伪代码 - 试图隔离问题。在应用程序中,它循环遍历字符串中的单词。
  • 一个可重现的、独立的示例来证明该问题会有所帮助。
  • 关于它 - 给我一个莫。
  • @MartinR 我需要知道你的午休时间安排,这样我才有机会获得一些 SO 业力。

标签: swift cocoa nsstring nsrange


【解决方案1】:

Swift String 字符描述“扩展字素簇”,NSString 使用 UTF-16 代码点,因此字符串的长度不同 取决于您使用的表示形式。

比如第一个字符"ยั"其实就是组合 "ย" (U+0E22) 的变音符号 " ั" (U+0E31)。 这算作一个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(" "))

【讨论】:

    【解决方案2】:

    删除nstextLessWordsWeHaveRangesFor 解决了这个问题(在底部以range.length &lt;= 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)

    【讨论】:

      猜你喜欢
      • 2015-06-26
      • 2015-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多