削减NSString的长度而不分割最后一个单词

时间:2012-09-24 20:47:52

标签: objective-c ios cocoa-touch

我试图在不使用此方法拆分最后一个单词的情况下缩短NSString的长度:

// cut a string by words
- (NSString* )stringCutByWords:(NSString *)string toLength:(int)length;
{
// search backwards in the string for the beginning of the last word
while ([string characterAtIndex:length] != ' ' && length > 0) {
    length--;
}

// if the last word was the first word of the string search for the end of the word
if (length <= 0){
    while ([string characterAtIndex:length] != ' ' && length > string.length-1) {
        length++;
    }
}

// define the range you're interested in
NSRange stringRange = {0, length};

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

// Now you can create the short string
string = [string substringWithRange:stringRange];

return [NSString stringWithFormat:@"%@...",string];
}

现在我的问题是: 在objective-c或cocoa-touch中是否存在我没​​有看到的内置方式,或者是否有一种“更好”的方式来实现这一点,因为我对这个解决方案并不满意。

问候并感谢您的帮助 C4rmel

2 个答案:

答案 0 :(得分:2)

我对类别方法的建议

@interface NSString (Cut)
-(NSString *)stringByCuttingExceptLastWordWithLength:(NSUInteger)length;
@end


@implementation NSString (Cut)

-(NSString *)stringByCuttingExceptLastWordWithLength:(NSUInteger)length
{
    __block NSMutableString *newString = [NSMutableString string];
    NSArray *components = [self componentsSeparatedByString:@" "];
    if ([components count] > 0) {
        NSString *lastWord = [components objectAtIndex:[components count]-1];

        [components enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
            if (([obj length]+[newString length] + [lastWord length] + 2) < length) {
                [newString appendFormat:@" %@", obj];
            } else {
                [newString appendString:@"…"];
                [newString appendFormat:@" %@", lastWord];
                *stop = YES;
            }
        }];

    }
    return newString;
}

用法:

NSString *string = @"Hello World! I am standing over here! Can you see me?";
NSLog(@"%@", [string stringByCuttingExceptLastWordWithLength:25]);

答案 1 :(得分:1)

建议:

  1. 使其成为一种类别方法;
  2. 使用NSCharacterSet和内置搜索方法,而不是自己动手。
  3. 所以:

    /* somewhere public */
    @interface NSString (CutByWords)
    - (NSString *)stringCutByWordsToMaxLength:(int)length
    @end
    
    /* in an implementation file, somewhere */
    
    @implementation NSString (CutByWords)
    
    // cut a string by words
    - (NSString *)stringCutByWordsToMaxLength:(int)length
    {
         NSCharacterSet *whitespaceCharacterSet =
                          [NSCharacterSet whitespaceCharacterSet];
    
         // to consider: a range check on length here?
         NSRange relevantRange = NSMakeRange(0, length);
    
         // find beginning of last word
         NSRange lastWordRange =
               [self rangeOfCharacterFromSet:whitespaceCharacterSet
                      options:NSBackwardsSearch
                      range:relevantRange];
    
         // if the last word was the first word of the string,
         // consume the whole string; this looks to be the same
         // effect as the original scan forward given that the
         // assumption is already made in the scan backwards that
         // the string doesn't end on a whitespace; if I'm wrong
         // then get [whitespaceCharacterSet invertedSet] and do
         // a search forwards
         if(lastWordRange.location == NSNotFound)
         {
              lastWordRange = relevantRange;
         }
    
        // adjust the range to include dependent chars
        stringRange = [self rangeOfComposedCharacterSequencesForRange:stringRange];
    
        // Now you can create the short string
        NSString *string = [self substringWithRange:stringRange];
    
        return [NSString stringWithFormat:@"%@...",string];
    }
    
    @end
    
    /* subsequently */
    
    NSString *string = ...whatever...;
    NSString *cutString = [string stringCutByWordsToMaxLength:100];