如何将 NSString 截断为设定的长度?

Posted

技术标签:

【中文标题】如何将 NSString 截断为设定的长度?【英文标题】:How can I truncate an NSString to a set length? 【发布时间】: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 安全的。有更好的方法吗?有人对此有一个不错的类别吗?

【问题讨论】:

...-substringToIndex:? 相关,按字节数截断而不是组合字符:Truncate string containing emoji or Unicode characters at word or character boundary 【参考方案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];

【讨论】:

以上是关于如何将 NSString 截断为设定的长度?的主要内容,如果未能解决你的问题,请参考以下文章

将字符串截断为设定长度,在单词边界处中断

将浮点数格式化为 NSString 时截断多余的零

如何截断Angular2中的文本?

PHP 将字符串长度截断为n个字符并使用...

本地 DB 抛出字节数组截断长度为 8000 的异常

将字符串 c++ 截断为长度而不剪切单词