31
votes

I just migrated our project to swift 3 and see lots of crashes because of one issue:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue pointSize]: unrecognized selector sent to instance

The reason for that error is the call to:

[NSAttributedString(NSExtendedStringDrawing) boundingRectWithSize:options:context:]

What I noticed is that if I cast String to NSString and call boundingRectWithSize on it it will throw that error. It also seems to be happening in many other parts, for example if I sent a view controller title in a storyboard it throws the same error.

Anyone having the same problems?

To reproduce the problem:

Create a new Swift 3 project in Xcode 8 and add the following line in viewDidLoad:

let attributes: [String: AnyObject?] = [
            NSFontAttributeName: UIFont.systemFont(ofSize: 14)
        ]
    let boundingRect = ("hello" as NSString).boundingRect(with: CGSize(width: 100, height: 100), options: .usesLineFragmentOrigin, attributes: attributes, context: nil)

But as I said it crashes in many other places as it seems that UIKit uses this method internally in many parts

3
Please show your code causing the issue with relevant parts.OOPer
Looks like it's related to the internal implementation of NSString3lvis
I'm getting the same crash but for this: (textLabel.text! as NSString).size(attributes: fontAttributes) I've tried everything from using nsmutablestring, appending strings to it etc. it still crashes. This is apples fault no doubt. Really really bad. Cannot migrate.ullstrm
Similar crash. What is Apple doing! (No I'm not force unwrapping "doing" ;) )Koushik Ravikumar

3 Answers

30
votes

If I use your test code, but let the data type of attributes default, it doesn't crash. That is:

let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: 14)]

Option-clicking on the variable says it's [String : UIFont].

A little extra testing, suggests that it's related to the optional object; [String: AnyObject] appears to work OK.

EDIT: And after all that, I decided to read the documentation, which says to use [String: Any]. :)

1
votes

The following fixed it for me:

let attributes: [String: UIFont] = [NSFontAttributeName: UIFont.systemFont(ofSize: 14)]
0
votes
func attributedString(firstText : String, amount : String, fontSize : CGFloat, color : UIColor) -> NSAttributedString {

    let attrDict = [ NSFontAttributeName : UIFont(name: fontRegular, size: CGFloat(fontSize/2))!,
                    NSForegroundColorAttributeName : UIColor.darkGray] as [String : AnyObject]
    let iconString = NSMutableAttributedString(string: firstText, attributes: attrDict)

    let attrDict1 = [ NSFontAttributeName : UIFont(name: fontRegular, size: CGFloat(fontSize))!,
                     NSForegroundColorAttributeName : color] as [String : AnyObject]
    let amountString = NSMutableAttributedString(string: amount, attributes: attrDict1)

    iconString.append(amountString)
    return iconString
}

And call it like

lblBalanceAmount.attributedText = self.attributedString(firstText: "My Balance", amount: "500", fontSize: newFontSize, color : UIColor(red: 41/255.0, green: 192/255.0, blue: 42/255.0, alpha: 1.0))