31

I get the error...

Could not find an overload for 'init' that accepts the supplied arguments

...when I try to use...

extension UIFont {
  func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
    NSString(string).boundingRectWithSize(CGSize(width, DBL_MAX),
                                          options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                                          attributes: [NSFontAttributeName: self],
                                          context: nil).size
  }
}

Does NSString not support this method anymore, or am I messing up on the syntax?

aleclarson
  • 18,087
  • 14
  • 64
  • 91
  • to see here, the same question with the raw swift way:[https://stackoverflow.com/questions/30450434/figure-out-size-of-uilabel-based-on-string-in-swift/30450559#30450559](https://stackoverflow.com/questions/30450434/figure-out-size-of-uilabel-based-on-string-in-swift/30450559#30450559) – zzycami Mar 31 '16 at 07:52

8 Answers8

76

The initializers expect named arguments.

extension UIFont {
    func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRectWithSize(CGSize(width: width, height: DBL_MAX),
            options: NSStringDrawingOptions.UsesLineFragmentOrigin,
            attributes: [NSFontAttributeName: self],
            context: nil).size
    }
}

Note: Strings can be cast to NSStrings.

extension UIFont {
    func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
        return (string as NSString).boundingRectWithSize(CGSize(width: width, height: DBL_MAX),
            options: NSStringDrawingOptions.UsesLineFragmentOrigin,
            attributes: [NSFontAttributeName: self],
            context: nil).size
    }
}

or

extension UIFont {
    func sizeOfString (string: NSString, constrainedToWidth width: Double) -> CGSize {
        return string.boundingRectWithSize(CGSize(width: width, height: DBL_MAX),
            options: NSStringDrawingOptions.UsesLineFragmentOrigin,
            attributes: [NSFontAttributeName: self],
            context: nil).size
    }
}

--

UPDATED

For Swift 4 syntax

extension UIFont {
    func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRect(
            with: CGSize(width: width, height: .greatestFiniteMagnitude),
            options: .usesLineFragmentOrigin,
            attributes: [.font: self],
            context: nil).size
    }
}
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
  • after using like this i am getting compile time error - "UIFont does not have a member sizeOfString" – Nitesh Dec 08 '14 at 08:22
  • @Nitesh Looks like you try to send `sizeOfString` to the `UIFont` (class) object. This one will not know about the new method, but its instances will. Try sending the method to a `UIFont` instance. Class methods can be defined in extensions too btw., though you would use `class fund …` to do that. – Patru Dec 16 '14 at 17:16
  • For any copy-pasters, if you get an error such as `pointSize]: unrecognized selector sent to instance`, it's because you need to replace the self in `[NSFontAttributeName: self]` with a font. – paulvs Apr 22 '16 at 19:26
4

Alternatively you could cast it into an NSString

if let ns_str:NSString = str as NSString? {

   let sizeOfString = ns_str.boundingRectWithSize(
                                 CGSizeMake(self.titleLabel.frame.size.width, CGFloat.infinity), 
                                 options: NSStringDrawingOptions.UsesLineFragmentOrigin, 
                                 attributes: [NSFontAttributeName: lbl.font], 
                                 context: nil).size
}
Mike M
  • 4,879
  • 5
  • 38
  • 58
4

Latest Swift

func sizeOfString (string: String, constrainedToHeight height: Double) -> CGSize {
    return NSString(string: string).boundingRect(with: CGSize(width: DBL_MAX, height: height),
                                                 options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                                 attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 20)],
                                                 context: nil).size
}
Amit Shekhar
  • 3,135
  • 2
  • 16
  • 17
1

Latest Swift:

import UIKit

extension UIFont {
    func sizeOfString(string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRect(with: CGSize(width: width, height: .greatestFiniteMagnitude),
                                                             options: .usesLineFragmentOrigin,
                                                             attributes: [NSFontAttributeName: self],
                                                             context: nil).size
    }
}
user3246173
  • 488
  • 6
  • 18
0

You can use objective-c bridging

let lblRegisterlinkWidth: CGFloat = lblRegisterLink.text!._bridgeToObjectiveC().boundingRectWithSize(lblRegisterLink.frame.size, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName : lblRegisterLink.font], context: nil).size.width
Varun Naharia
  • 5,318
  • 10
  • 50
  • 84
0

Swift 4.1 version

extension UIFont {
    func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRect(with: CGSize(width: width, height: .greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: self], context: nil).size
    }
}
Abhishek Jain
  • 4,557
  • 2
  • 32
  • 31
0

Latest Swift 5:

extension UIFont {
    func size(OfString string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRect(with: CGSize(width: width, height: .greatestFiniteMagnitude),
                                                     options: .usesLineFragmentOrigin,
                                                     attributes: [.font: self],
                                                     context: nil).size
    }
}
black_pearl
  • 2,549
  • 1
  • 23
  • 36
0

Swift 5

extension String {
    func sizeOfString(maxWidth: CGFloat, font: UIFont) -> CGSize {
        let tmp = NSMutableAttributedString(string: self, attributes:[NSAttributedString.Key.font: font])
        let limitSize = CGSize(width: maxWidth, height: CGFloat(MAXFLOAT))
        let contentSize = tmp.boundingRect(with: limitSize, options: .usesLineFragmentOrigin, context: nil)
        return contentSize.size
    }
}
pckill
  • 3,709
  • 36
  • 48
Johnny
  • 97
  • 1
  • 2