33

I am trying to get the width of an NSString (ex. NSString *myString = @"hello"). Is there a way to do this?

Thanks.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
David
  • 14,205
  • 20
  • 97
  • 144

12 Answers12

62

Here's a relatively simple approach. Just create an NSAttributedString with the appropriate font and ask for its size:

- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
     return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
 }
Stephen Poletto
  • 3,645
  • 24
  • 24
  • 2
    That leaks the attributed string. – Peter Hosey Aug 07 '10 at 08:28
  • 10
    True - I've assumed a garbage collected environment. – Stephen Poletto Aug 07 '10 at 08:35
  • 2
    Just use `sizeWithAttributes:` on the string instead: `return [string sizeWithAttributes:attributes].width;` – jowie Jun 26 '14 at 15:56
  • For the purpose of just getting the width of a string , it seems to work just by initing the atribString with string, and asking for the size.width. I don't think you need to give it any attributes. There may be times when you won't know the font attributes. Yes alloc and release the string. This is working for me. Thank You – Miek Jul 31 '14 at 15:37
15
UIFont * font = [UIFont systemFontOfSize:15];

CGSize stringSize = [aString sizeWithFont:font]; 

CGFloat width = stringSize.width;
joker
  • 319
  • 3
  • 10
  • 8
    sizeWithFont is now deprecated. It should now look like CGSize stringSize = [aString sizeWithAttributes:@{NSFontAttributeName:font}]; – RasTheDestroyer Sep 18 '14 at 00:26
5

Using the UILabel's attributed string:

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

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

    return label.attributedText.size;
}
Amr Lotfy
  • 2,937
  • 5
  • 36
  • 56
3

i dont know if you are suppose to use this in cocoa touch. if it is, then:

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

wont work.

in cocoa touch, you gotta add coretext framework and import the header and write your code like this:

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

but, GEE!!!!!

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

there's no size this method in NSMutableAttributedString!

finally, this would work

[self.caption sizeWithFont:font].width
Bruce Lee
  • 4,177
  • 3
  • 28
  • 26
3

Send the string a sizeWithAttributes: message, passing a dictionary containing the attributes with which you want to measure the string.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
2

as for ios 7 and up this is the correct way:

NSString * buttonTitle = @"demo title";
CGSize stringSize = [buttonTitle sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];
Eli
  • 586
  • 2
  • 12
  • 28
1

This works with iOS 14.5

Objective-C

Define attributes:

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

Get width and height:

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

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

dotrinh PM
  • 903
  • 1
  • 7
  • 19
0

Here's Stephen's solution in Clozure Common Lisp, when using the Objective C bridge. I came across this post when searching for a solution, and I just rewrote Stephen's version which worked fine for me. Others using Clozure might find this helpful:

(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)))
Clayton Stanley
  • 7,513
  • 9
  • 32
  • 46
0

Sorry my question was not detailed enough and is not exactly what I'm trying to do. I am using a text storage, layout manager and a text container. The solution is to use the layout manager to determine the rectangle that bounds the rect. Here is the code.

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];
David
  • 14,205
  • 20
  • 97
  • 144
  • That's the long way. If you normally have a text storage, layout manager, and text container anyway (and having a text view counts), then that's fine, but there are a couple of much shorter ways. – Peter Hosey Aug 07 '10 at 08:30
  • Wouldn't assign to `NSTextField` the desired string and then calling for `sizeToFit` method ->Then retrieve the width from `NSTextField` would be better ? (I have the same problem just want to do this properly) – Coldsteel48 Oct 06 '15 at 10:53
0

UIKit has a nice addition to NSString, making sizeWithAttributes: a bit lighter:

CGSize titleSize = [title sizeWithFont:titleFont 
                     constrainedToSize:contentCellSize 
                         lineBreakMode:UILineBreakModeWordWrap];
Mullzk
  • 9
  • 3
0

This will work. You can try it.

NSDictionary *attrDict = @{NSFontAttributeName : [GenericUtility getOpenSansRegularFontSize:12]};
CGSize stringBoundingBox = [selectedReservationModel.DateLabel sizeWithAttributes: attrDict];
    lblDeliveryDateWidth = stringBoundingBox.width;
sametytmz
  • 9
  • 2
-1

Just in case you are wondering how to check a label size, you should use the UIFont, instead of the NSFont (not even sure if exists)