Как узнать длину строки NSString, которая соответствует UILabel с фиксированным размером? - PullRequest
10 голосов
/ 21 июня 2011

Я знаю, что у NSString есть методы, которые определяют размер кадра для него, используя NSString UIKit Additions, sizeWithFont ......

Как насчет обратного? Я имею в виду, что если у меня фиксированный размер фрейма, как узнать, сколько символов или слов в строке NSString может вписаться в него?

Если я знаю это, я могу легко отключить строку NSString.

спасибо

Ответы [ 4 ]

7 голосов
/ 21 июня 2011

Возможно, это не самое элегантное решение, но вы можете сделать что-то вроде этого:

- (NSString *)string:(NSString *)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont *)font {

    if ([sourceString sizeWithFont:font].width <= width)
        return sourceString;

    NSMutableString *string = [NSMutableString string];

    for (NSInteger i = 0; i < [sourceString length]; i++) {

        [string appendString:[sourceString substringWithRange:NSMakeRange(i, 1)]];

        if ([string sizeWithFont:font].width > width) {

            if ([string length] == 1)
                return nil;

            [string deleteCharactersInRange:NSMakeRange(i, 1)];

            break;
        }
    }

    return string;
}

Затем назовите это так:

NSString *test = @"Hello, World!";
CGFloat width = 40.0;
UIFont *font = [UIFont systemFontOfSize:[UIFont labelFontSize]];

NSString *reducedString = [self string:test reducedToWidth:width withFont:font];

NSLog(@"%@", reducedString);
1 голос
/ 21 июня 2011

Вы не можете знать / определить количество символов, которое умещается в UILabel с фиксированной шириной, поскольку некоторые символы меньше, чем другие, например, l и m.

Есть два варианта:

  1. Используйте моно-космические шрифты (каждый символ также имеет фиксированную ширину).Затем определите ширину для одного символа в вашем шрифте с вашим размером шрифта и рассчитайте количество символов
  2. Разрешите любое количество символов и проверьте вставку, если вставленные символы соответствуют.

Вы должны знать, какое поведение вы хотите иметь.Что должно произойти, если есть текст, который не подходит.Если вы хотите только усечь (как это делает решение mortenfast), просто используйте UILineBreakModeTailTruncation для lineBreakMode -войства вашего UILabel (есть и другие опции, такие как TruncateHead, Clip, Word Wrap)

0 голосов
/ 17 марта 2015

Или вы просто используете свойство lineBreak и устанавливаете его в NSLineBreakByCharWrapping и продолжаете свою жизнь.https://stackoverflow.com/a/29088337/951349

0 голосов
/ 19 сентября 2012

Спасибо @ Мортен.Я обновил пример кода для обработки слов.Это также устраняет лишние пробелы между словами.Он не был испытан в полевых условиях, но мои тесты, к настоящему времени, доказали, что все в порядке.Пожалуйста, обновляйте на досуге, если вы найдете улучшения или исправления ошибок / сбоев.

-(NSString*)string:(NSString*)sourceString reducedToWidth:(CGFloat)width withFont:(UIFont*)font {

    // if full string is within bounds, simply return the full string
    if( [sourceString sizeWithFont:font].width <= width ) return sourceString;

    // break up string into words. if <= 1 word, return original string
    NSArray* words = [sourceString componentsSeparatedByString:@" "];
    NSInteger numWords = [words count];
    if( numWords <= 1 ) return sourceString;

    // our return var. we populate as we go
    NSMutableString* str = [NSMutableString string];
    // temp var to test with before adding to return string
    NSMutableString* strTemp = [NSMutableString string];
    // string to hold word LESS spaces
    NSString* strWordTemp = nil;
    // the word we're currently on
    NSInteger numWord = 0;
    // whether we need to add a space (when not last word)
    Boolean addSpace = NO;

    // loop through our words....
    for( NSString* strWord in words ) {

        // which word we're on
        numWord++;

        // eliminate white space
        strWordTemp = [strWord stringByReplacingOccurrencesOfString:@" " withString:@""];

        // if this word is empty or was a space(s), skip it
        if( [strWordTemp isEqualToString:@""] ) continue;

        // append to temp string
        [strTemp appendString:strWordTemp];

        // if we're still within the bounds...
        if( [strTemp sizeWithFont:font].width <= width ) {

            // default = no extra space
            addSpace = NO;

            // if we're not the last word, add a space & check for length
            if( numWord < numWords ) {

                [strTemp appendString:@" "];

                // if adding space made it too long, then just don't add it!
                if( [strTemp sizeWithFont:font].width > width ) {

                    // it was too long with space, so we'll just add word
                    [str appendString:strWordTemp];
                    break;
                }
                // otherwise, it's OK to add the space
                else addSpace = YES;
            }

            // append to return string and continue
            [str appendFormat:@"%@%@", strWordTemp, ( addSpace ? @" " : @"" )];
        }
        // otherwise, we're done
        else break;
    }

    // return our result
    return str;
}
...