【问题标题】:How can I truncate an NSString to a set length?如何将 NSString 截断为设定的长度?
【发布时间】:2010-06-01 18:33:42
【问题描述】:

我搜索了,但令人惊讶的是找不到答案。

我想缩短一个很长的NSString。我希望最大长度约为 20 个字符。我在某处读到最好的解决方案是使用substringWithRange。这是截断字符串的最佳方法吗?

NSRange stringRange = {0,20};
NSString *myString = @"This is a string, it's a very long string, it's a very long string indeed";
NSString *shortString = [myString substringWithRange:stringRange];

看起来有点微妙(如果字符串短于最大长度会崩溃)。我也不确定它是否是 Unicode 安全的。有更好的方法吗?有人对此有一个不错的类别吗?

【问题讨论】:

标签: iphone objective-c cocoa string


【解决方案1】:

实际上,关于“Unicode 安全”的部分已经结束,因为许多字符组合成 unicode,建议的答案没有考虑。

例如,如果您想输入 é。一种方法是输入“e”(0x65)+组合重音“́”(0x301)。现在,如果您像这样键入“café”并截断 4 个字符,您将得到“cafe”。这可能会在某些地方引起问题。

如果您不关心这一点,其他答案也可以。否则,请执行以下操作:

// define the range you're interested in
NSRange stringRange = {0, MIN([myString length], 20)};

// adjust the range to include dependent chars
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];

// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];

请注意,通过这种方式,您的范围可能会比您的初始范围长度长。在上面的咖啡馆示例中,您的范围将扩展到 5 的长度,即使您仍然有 4 个“字形”。如果您绝对需要长度小于您指定的长度,则需要检查这一点。

【讨论】:

  • 感谢您的回答。日语汉字是否受到您提到的组合重音问题的影响?通过使用您的解决方案,它似乎与汉字配合得很好。
  • 恐怕我对汉字字符不是很熟悉,但我想它们都是单个字符(unicode 0x4E00 到 0x9FAF)所以他们不应该需要这个。但同样,我不确定......
  • @mohsenr 我刚刚在截断前后(使用 OP 的解决方案)测试了“café”,两者都给出了 4 的长度。我认为 iOS 将 'é' 视为单个字符! !
  • 'é' = 0xE9 和'é' = 0x65 0x301。如果第一种情况,第二个 5 中的长度为 4。
【解决方案2】:

斯威夫特 4

let trimToCharacter = 20
let shortString = String(myString.prefix(trimToCharacter))

快乐编码。

【讨论】:

    【解决方案3】:

    由于此答案实际上不在此列表中,因此最简单,最明智的单行:

    NSString *myString = @"This is a string, it's a very long string, it's a very long string indeed";
    myString = (myString.length > 20) ? [myString substringToIndex:20] : myString;
    

    【讨论】:

    • 太棒了!因为我不能编辑一个字符拼写错误,所以我把它放在这里:[myString subStringToIndex:20];应该是 [myString substringToIndex:20];
    • 如果myString.lenght 高于20,我会抛出异常。您必须先对其进行测试
    【解决方案4】:

    更短的解决方案是:

    NSString *shortString = ([myString length]>MINLENGTH ? [myString substringToIndex:MINLENGTH] : myString);
    

    【讨论】:

      【解决方案5】:

      看起来有点微妙(如果字符串短于最大长度会崩溃)

      那为什么不修复那部分呢?

      NSRange stringRange = {0, MIN([myString length], 20)};
      

      【讨论】:

        【解决方案6】:

        可以使用三元运算:

        NSString *shortString = (stringRange.length <= [myString length]) ? myString : [myString substringWithRange:stringRange];
        

        或者为了更好地控制最终结果:

        if (stringRange.length > [myString length])
            // throw exception, ignore error, or set shortString to myString
        else 
            shortString = [myString substringWithRange:stringRange];
        

        【讨论】:

          【解决方案7】:

          最简单又好看的解决方案(文末3个点):

          NSString *newText = [text length] > intTextLimit ? 
              [[text substringToIndex:intTextLimit] stringByAppendingString:@"..."] : 
                  text;
          

          【讨论】:

          • 你应该使用“…”(Option + ;)而不是 3 个点,它只需要一个字符。
          【解决方案8】:
           //Short the string if string more than 45 chars
              if([self.tableCellNames[indexPath.section] length] > 40) {
          
                  // define the range you're interested in
                  NSRange stringRange = {0, MIN([self.tableCellNames[indexPath.section] length], 40)};
          
                  // adjust the range to include dependent chars
                  stringRange = [self.tableCellNames[indexPath.section]
                                 rangeOfComposedCharacterSequencesForRange:stringRange];
          
                  // Now you can create the short string
                  NSString *shortStringTitle = [self.tableCellNames[indexPath.section] substringWithRange:stringRange];
          
                  shortStringTitle = [shortStringTitle stringByAppendingString:@"..."];
          
                  titleLabel.text = shortStringTitle;
          
              } else {
          
                  titleLabel.text = self.tableCellNames[indexPath.section];
              }
          

          //VKJ

          【讨论】:

            【解决方案9】:

            在不同位置(头部、尾部或中间)截断的扩展。

            Swift 4.2 及更新版本

            extension String {
                enum TruncationPosition {
                    case head
                    case middle
                    case tail
                }
            
               func truncated(limit: Int, position: TruncationPosition = .tail, leader: String = "...") -> String {
                    guard self.count >= limit else { return self }
            
                    switch position {
                    case .head:
                        return leader + self.suffix(limit)
                    
                    case .middle:
                        let halfCount = (limit - leader.count).quotientAndRemainder(dividingBy: 2)
                        let headCharactersCount = halfCount.quotient + halfCount.remainder
                        let tailCharactersCount = halfCount.quotient
                        return String(self.prefix(headCharactersCount)) + leader + String(self.suffix(tailCharactersCount))
                    
                    case .tail:
                        return self.prefix(limit) + leader
                    }
                }
            }
            

            【讨论】:

              【解决方案10】:

              所有 NSString 操作都是 Unicode 安全的,因为 NSString 在内部本质上是一个 unichar 数组。即使字符串采用不同的编码,它也会在显示时转换为您指定的编码。

              【讨论】:

              • 实际上,不,它并不完全是 Unicode 安全的,因为某些 Unicode 字符使用多个 unichar。您希望避免在这样的序列中间拆分字符串。因此需要像rangeOfComposedCharacterSequenceAtIndex: 这样的方法。
              【解决方案11】:

              如果您想从最终用途中截断:

              [fileName substringToIndex:anyNumber];
              

              如果你想从头开始截断:

              [fileName substringFromIndex:anyNumber];
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-09-13
                • 2020-12-05
                • 2018-01-14
                • 1970-01-01
                • 2012-03-25
                • 1970-01-01
                • 2021-05-09
                • 1970-01-01
                相关资源
                最近更新 更多