views:

136

answers:

5

I searched, but surprisingly couldn't find an answer.

I have a long NSString that I want to shorten. I want the maximum length to be around 20 characters. I read somewhere that the best solution is to use substringWithRange. Is this the best way to truncate a string?

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

It seems a little delicate (crashes if the string is shorter than the maximum length). I'm also not sure if it's Unicode-safe. Is there a better way to do it? Does anyone have a nice category for this?

+1  A: 

Could use a ternary operation:

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

Or for more control over the end result:

if (stringRange.length > [myString length])
    // throw exception, ignore error, or set shortString to myString
else 
    shortString = [myString substringWithRange:stringRange];
Alex Reynolds
Nice one-liner, thanks Alex.
nevan
+3  A: 

It seems a little delicate (crashes if the string is shorter than the maximum length)

Then why not fix that part of it?

NSRange stringRange = {0, MIN([myString length], 20)};
Shaggy Frog
Nice solution, thanks.
nevan
A: 

All NSString operations are Unicode-safe, as NSString is essentially a unichar array internally. Even if the string is in a different encoding it's converted to your specified encoding when it's displayed.

jshier
Actually, no, it's not exactly Unicode-safe, since some Unicode characters use more than one unichar. You want to avoid splitting a string in the middle of such a sequence. Hence the need for methods like `rangeOfComposedCharacterSequenceAtIndex:`.
JWWalker
+7  A: 

Actually the part about being "Unicode safe" was dead on, as many characters combine in unicode which the suggested answers don't consider.

For example, if you want to type é. One way of doing it is by typing "e"(0x65)+combining accent" ́"(0x301). Now, if you type "café" like this and truncate 4 chars, you'll get "cafe". This might cause problems in some places.

If you don't care about this, other answers work fine. Otherwise, do this:

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

Note that in this way your range might be longer than your initial range length. In the café example above, your range will expand to a length of 5, even though you still have 4 "glyphs". If you absolutely need to have a length less than what you indicated, you need to check for this.

Mo
Thanks for the answer. Are Japanese kanji affected by the combining accent problem that you mentioned? From using your solution, it seems to work well with kanji.
nevan
I'm afraid I'm not that familiar with kanji characters, but I suppose they're all single characters (unicode 0x4E00 to 0x9FAF) so they shouldn't need this. But again, I'm not sure...
Mo
A: 

Here is an example I wrote that truncates to a specific pixel width based on a specific font:

Truncate a String and Append an Ellipsis, Respecting the Font Size

Hope that helps.

iOSDevTips.com

John