NSString* str = @"hello kitty, would you tell me why do you want to go to shanghai?"; 
     
    //这一句,我要怎么才能知道上面文字分行之后的确切高度,而不是给定一个固定值200? 
    [str drawInRect:NSMakeRect(10, 20, 100, 200) withAttributes:nil]; 
     
    [str release];

解决方案 »

  1.   

    - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode;
    此方法可以计算出文字放到一个固定的(constrainedToSize)大小里面的宽高;
    比如你的:CGSize strSize = [str sizeWithFont:[UIFont systemFontOfSize:16]
                         constrainedToSize:CGSizeMake(100, CGFLOAT_MAX)
                             lineBreakMode:UILineBreakModeCharacterWrap];
      

  2.   

    在网上找了一段文字,没看懂........ 
    /////////////////////////////////////////// 
     
    Core Text提供了一系列方便的函数,可以很容易的把文本绘制在屏幕上,对于一个Frame来说,一般并不需要担心文本的排列问题,这些Core Text的函数都可以直接搞定,只要给他一个大小合适的CGRect就可以。 
    但,在某些情况下,我们还希望知道这段文本在绘制之后,对应绘制的字体字号设置,在屏幕上实际占用了多大面积。举例来说,有文本段落a,屏幕大小 rect,通常做法是以rect创建path,然后创建CTFramesetter,再然后创建CTFrame,最后用CTFrameDraw画出来,这 时候,往往文本段落占用的实际面积会小于rect,这时候就有必要获得这段文本所占用的真正面积。 
    最理想的情况是使用 
    double CTLineGetTypographicBounds( CTLineRef line, CGFloat* ascent, CGFloat* descent, CGFloat* leading ); 
    这是Core Text提供的函数,传入CTLine,就会得到这一行的ascent,descent和leading,在OSX上通常可以工作的很好,但是在 iOS(iPhone/iPad)上这个函数的结果略有不同。 
    正常情况下,计算行高只需要ascent+descent+leading即可。在这个略有不同的情况下,leading的值会出现偏差,导致算出 来的结果是错误的。如果不管行距,ascent+descent计算出来的Glyph的高度还是正确的。 
    这样就有了第一步 
    在创建用于绘图的CFAttributedStringRef时,除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该 确定行距kCTParagraphStyleSpecifierLineSpacing。在计算这里时,先逐行计算ascent+descent,累加起 来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实际高度,CTLineGetTypographicBounds返回的结果是宽度, 这样就可得到文本实际填充面积的Rect了。 
    但是这还是有问题,因为OSX上和iOS处理不同,所以事实上iOS的模拟器和真机的最终效果是不一样的,这样调试程序很麻烦。 
    于是还需要第二步 
    在最终往页面上绘制的时候,不再用CTFrameDraw来一次绘制全部,而是使用CTLineDraw逐行画,在画之前,先用 CGContextSetTextPosition来设置好每行文本的位置。这样就保证了在任何平台上绘制效果一致。 
    问题就解决了。 
    CoreText在OS X和iOS上实现有很多细节区别,比如说,对CTRun的划分方式也不一样,在iOS上划分出来的Run数量比OSX上少很多,是按照字体划分的Run, 按照文档出来,这是正确的,但OSX上是一个字一个Run这样划分的,和文档不符。iOS上的处理显然效率更好。 
    stackoverflow 上有一个类 似的讨论,不过没考虑到iOS的区别 
      

  3.   


    //以下代码没有正确计算出文字的高度...大家看看哪里出错了? 
     
    - (int)getAttributedStringHeightWithString:(NSAttributedString*)string WidthValue:(int)width { 
        int h = 10000; //[string length] * 40; 
         
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string); //string为要计算高度的NSAttributedString 
        CGMutablePathRef path = CGPathCreateMutable(); 
        CGPathAddRect(path, NULL, CGRectMake(0, 0, width, h)); //这里的高要设置足够大 
        CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); 
        CGPathRelease(path); 
        CFRelease(framesetter); 
         
        NSArray* linesArray = (NSArray*)CTFrameGetLines(textFrame); 
        NSUInteger count = [linesArray count]; 
        if(count <= 0) { 
            CFRelease(textFrame); 
            return 0; 
        } 
        CGPoint origins[count]; 
        CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins); 
        CGFloat line_y = origins[count - 1].y; //最后一行line的原点y坐标 
         
        CGFloat ascent, descent, leading; 
        CTLineRef line = (CTLineRef)[linesArray objectAtIndex: [linesArray count] - 1]; 
        CTLineGetTypographicBounds(line, &ascent, &descent, &leading); 
        CGFloat total_height = h - line_y + ascent + descent + leading + 1; //+1为了纠正descent转换成int小数点后舍去的值 
         
        CFRelease(textFrame); 
        return total_height; 

     
    - (void)drawRect:(NSRect)dirtyRect { 
        NSString* str = @"hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起\n\ 
        楞个圾有圾和在有了上国有和国因为相关爆发\n正常情况下,计算行高只需要ascent+descent+leading即可。\n\ 
        在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,\n\ 
        ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,\n\ 
        除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。\n\ 
        在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实\n\ 
        际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了"; 
     
        NSAttributedString* string = [[NSAttributedString alloc] initWithString:str]; 
        int h = [self getAttributedStringHeightWithString:string WidthValue:200]; 
        [str drawInRect:NSMakeRect(0, 0, 200, h) withAttributes:nil]; 
         
        [string release]; 
        [str release]; 
    }
      

  4.   

    因为我是在OS X下,而不是iOS下.有些不同以下代码,绘出来的是
    NSString *labelString = @"hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起\n\
    楞个圾有圾和在有了上国有和国因为相关爆发正常情况下,计算行高只需要ascent+descent+leading即可。\n\
    在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,\n\
    ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,\n\
    除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。\n\
    在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实\n\
    际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了";

        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]], NSFontAttributeName,
    //[NSColor redColor], NSForegroundColorAttributeName,
    //[NSColor yellowColor], NSBackgroundColorAttributeName,
    nil];

        NSSize labelSize = [labelString sizeWithAttributes:attributes];
        NSRect labelRect = NSMakeRect(0, 0, labelSize.width, labelSize.height);
        [labelString drawInRect:labelRect withAttributes:attributes];
    ///////////////////////////
    hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起
    楞个圾有圾和在有了上国有和国因为相关爆发正常情况下,计算行高只需要ascent+descent+leading即可。
    在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,
    ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,
    除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。
    在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实
    际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了//////////////////////////
    没有在200处分行,实事上我需要分行,效果如下,怎么实现呢?///////////////////////
    hello kitty, would you tell me why do you 
    want to go to shanghai? 真心伤不起
    楞个圾有圾和在有了上国有和国因为相关
    爆发正常情况下,计算行高只需要ascent+
    descent+leading即可。
    在这个略有不同的情况下,leading的值会
    出现偏差,导致算出来的结果是错误的。如果不
    管行距,
    ascent+descent计算出来的Glyph的高度
    还是正确的。这样就有了第一步在创建用于绘图
    的CFAttributedStringRef时,
    除了设置字体,多设置一个
    CTParagraphStyleRef,其中特别应该确定行距
    kCTParagraphStyleSpecifierLineSpacing。
    在计算这里时,先逐行计算ascent+
    descent,累加起来,再加上一个行数*之前设置
    好的行距,这样算出来的就是这些文本的实
    际高度,
    CTLineGetTypographicBounds返回的结果是宽
    度,这样就可得到文本实际填充面积的Rect了