如何获取NSString的宽度?

33

我试图获取NSString的宽度(例如:NSString *myString = @"hello")。有没有办法做到这一点?

谢谢。


可能是如何获取NSString的大小的重复问题。 - Jaanus
4
不行,因为那个问题是关于Cocoa Touch的,而这个问题是关于Cocoa的。 - Peter Hosey
@Peter Hosey,非常好的观察。 - Jaanus
12个回答

62

这是一个相对简单的方法。只需使用适当的字体创建NSAttributedString,并询问其大小:

- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
     return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
 }

2
泄漏了属性字符串。 - Peter Hosey
10
真 - 我假设了一个垃圾回收环境。 - Stephen Poletto
2
只需在字符串上使用 sizeWithAttributes:return [string sizeWithAttributes:attributes].width; - jowie
为了仅获取字符串的宽度,似乎只需使用字符串来初始化atribString,并请求size.width即可。我认为您不需要指定任何属性。有时您可能不知道字体属性。是的,需要分配和释放字符串。这对我有用。谢谢。 - Miek

15
UIFont * font = [UIFont systemFontOfSize:15];

CGSize stringSize = [aString sizeWithFont:font]; 

CGFloat width = stringSize.width;

8
sizeWithFont方法已经被弃用,现在应该使用如下方式:CGSize stringSize = [aString sizeWithAttributes:@{NSFontAttributeName:font}];注意不要改变原本的含义。 - RasTheDestroyer

5

使用UILabel的属性字符串:

- (CGSize)getStringSizeWithText:(NSString *)string font:(UIFont *)font{

    UILabel *label = [[UILabel alloc] init];
    label.text = string;
    label.font = font;

    return label.attributedText.size;
}

3

我不知道在Cocoa Touch中是否应该使用这个。如果是的话:

- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
     return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
 }

无法工作。

在Cocoa Touch中,您需要添加CoreText框架并导入标头,并像这样编写您的代码:

UIFont *font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:DEFAULT_FONT_SIZE];
//    NSLog(@"%@", NSFontAttributeName);
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, (NSString     *)kCTFontAttributeName, nil];

但是,天哪!

NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:self.caption attributes:attributes];
[as size].width;

在NSMutableAttributedString中没有这种方法的尺寸!

最后,这将起作用。

[self.caption sizeWithFont:font].width

2
这是我很长时间以来见过最令人困惑的答案。你能发布完整的代码片段吗? - chrisallick

3

发送字符串一个sizeWithAttributes:消息,传递包含您想要测量字符串的属性的字典。


2

对于 iOS 7 及以上版本,以下是正确的方法:

NSString * buttonTitle = @"demo title";
CGSize stringSize = [buttonTitle sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];

1

这适用于iOS 14.5版本

Objective-C

定义属性:

 NSDictionary *attributes = @{
            NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:25],
            NSStrokeWidthAttributeName: @(0),
            NSStrokeColorAttributeName: [UIColor blackColor]
    };

获取宽度和高度:

- (CGFloat)widthOfString:(NSString *)string {
    CGSize stringSize = [string sizeWithAttributes:attributes];
    return stringSize.width;
}

- (CGFloat)heightOfString:(NSString *)string {
    CGSize stringSize = [string sizeWithAttributes:attributes];
    return stringSize.height;
}


0

抱歉我的问题没有详细说明,也不是我想要做的事情。我正在使用文本存储、布局管理器和文本容器。解决方案是使用布局管理器来确定包围矩形的矩形。以下是代码。

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:@"hello"];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] init];

[layoutManager addTextContainer:textContainer];
[textContainer release];

[textStorage addLayoutManager:layoutManager];
[layoutManager release];

//Figure out the bounding rectangle
NSRect stringRect = [layoutManager boundingRectForGlyphRange:NSMakeRange(0, [layoutManager numberOfGlyphs]) inTextContainer:textContainer];

那是一种冗长的方式。如果你通常已经有文本存储、布局管理器和文本容器(并且拥有文本视图也算),那么这很好,但还有几种更短的方式。 - Peter Hosey
把所需的字符串分配给 NSTextField,然后调用 sizeToFit 方法可能不是最好的选择,从 NSTextField 中检索宽度会更好吗?(我有同样的问题,只是想正确地解决它) - Coldsteel48

0

UIKit对NSString进行了不错的补充,使得sizeWithAttributes:方法更加轻便:

CGSize titleSize = [title sizeWithFont:titleFont 
                     constrainedToSize:contentCellSize 
                         lineBreakMode:UILineBreakModeWordWrap];

sizeWithFont 已被弃用。 - Amr Lotfy

0

这是Stephen在使用Objective C桥接时在Clozure Common Lisp中的解决方案。我在寻找解决方案时遇到了这篇文章,然后我重新编写了Stephen的版本,这对我很有效。其他使用Clozure的人可能会发现这很有帮助:

(defun string-width (str font)
  (let* ((dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
                font #$NSFontAttributeName
                ccl:+null-ptr+))
         (attr (#/initWithString:attributes: (#/alloc ns:ns-attributed-string)
                (ccl::%make-nsstring str)
                dict))
         (size (#/size attr)))
    (ns:ns-size-width size)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接