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


69

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

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安全的。有更好的方法吗?有人对此有很好的分类吗?


7
... -substringToIndex:
kennytm 2010年

1
相关,按字节计数而不是组成字符截断
jscs 2015年

Answers:


123

实际上,关于“ 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];

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


感谢你的回答。您提到的合并口音问题会影响日本汉字吗?通过使用您的解决方案,它似乎可以与汉字一起使用。

恐怕我对汉字字符不太熟悉,但是我想它们都是单个字符(unicode 0x4E00到0x9FAF),因此他们不需要此字符。但是同样,我不确定...
mohsenr 2010年

@mohsenr我刚刚在截断之前和之后(使用OP的解决方案)使用“café”进行了测试,两者的长度均为4。我认为iOS将'é'视为单个字符!
onmyway133

'é'= 0xE9和'é'= 0x65 0x301。如果是第一种情况,则第二个长度为
4。– dimaxyu

15

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

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];
user23127 2014年

如果myString.lenght高于,我抛出异常20。您必须先进行测试
Axel Guilmin 2014年

11

较短的解决方案是:

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


7

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

那为什么不修复它的那一部分呢?

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

3

可以使用三元运算:

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];

3

最简单又好用的解决方案(在文本末尾带有3个点):

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

2
不应使用3个点,而应使用仅包含一个字符的“…”(Option +;)。
atulkhatri

2
 //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


2

扩展以截断不同位置(头,尾或中间)。

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
        }
    }
}

0

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


4
实际上,不,这并不是完全安全的Unicode,因为某些Unicode字符使用多个unichar。您要避免在这样的序列中间拆分字符串。因此需要像这样的方法rangeOfComposedCharacterSequenceAtIndex:
JWWalker 2010年

0

如果要从最终用途中截断:

[fileName substringToIndex:anyNumber];

如果要从头开始截断:

[fileName substringFromIndex:anyNumber];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.