有效地确定IOS中UILabel可以容纳多少文本

时间:2015-09-30 16:50:41

标签: optimization nsstring uilabel

我有一个NSString,我想知道该字符串中有多少适合UILabel。

我的代码通过从原始字符串一次添加一个字符来构建测试字符串。每次添加一个字符时,我都会测试新字符串,看它是否适合我的标签:

CGRect cutTextRect = [cutText boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:stringAttributes context:nil];

然后我将该rect的高度与我的标签高度进行比较,以查看该字符串是否溢出。

这很有效,但是乐器告诉我循环占用了我所有的cpu时间。

有人能想到或知道更快的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

虽然不是最漂亮的:

- (NSString *)stringForWidth:(CGFloat)width fullString:(NSString *)fullString
{
    NSDictionary *attributes = @{NSFontAttributeName: label.font};

    if ([fullString sizeWithAttributes:attributes].width <= width)
    {
        return fullString;
    }

    // Might be worth researching more regarding 'average' char size 
    CGFloat approxCharWidth = [@"N" sizeWithAttributes:attributes].width;

    NSInteger approxNumOfChars = (NSInteger)(width / approxCharWidth);

    NSMutableString *resultingString = [NSMutableString stringWithString:[fullString substringToIndex:approxNumOfChars]];

    CGFloat currentWidth = [resultingString sizeWithAttributes:attributes].width;

    if (currentWidth < width)
    {
        // Try to 'sqeeze' another char.
        while (currentWidth < width && approxNumOfChars < fullString.length)
        {
            approxNumOfChars++;

            [resultingString appendString:[fullString substringWithRange:NSMakeRange(approxNumOfChars - 1, 1)]];

            currentWidth = [resultingString sizeWithAttributes:attributes].width;
        }
    }

    // String might be oversized
    if (currentWidth > width)
    {
        while (currentWidth > width)
        {
            [resultingString deleteCharactersInRange:NSMakeRange(resultingString.length - 1, 1)];

            currentWidth = [resultingString sizeWithAttributes:attributes].width;
        }
    }

    // If dealing with UILabel, it's safer to have a smaller string than 'equal',
    // 'clipping wise'. Otherwise, just use '<=' or '>=' instead of '<' or '>'

    return [NSString stringWithString:resultingString];
}

有几个循环,但每个循环都是'微调',应该只运行很少次。

提高效率的一种方法是获得一个更好的起点,而不是计算给定宽度中可以容纳多少个N. 我愿意接受有关这方面的建议。

<强> - 编辑:

关于多行标签,一旦我知道宽度的给定文本,我可以预期以下文本(如果有的话)将转到下一行。

换句话说,获取' text for width '是一个棘手的部分,'文本宽度'我们免费获得。