LearningGuy
LearningGuy

Reputation: 191

unexpectedly found nil while unwrapping an Optional value from NSMutableString

I can't get around this error. When I run this function I get a fatal error. fatal error: unexpectedly found nil while unwrapping an Optional value below is the function:

func changeSelectedFontColor(fontColor: UIColor) {

    let selectedRange : NSRange = self.textView.selectedRange

    var currentAttributesDict : NSDictionary = textView.textStorage.attributesAtIndex(selectedRange.location, effectiveRange: nil)

    var currentFont : UIFont = currentAttributesDict.objectForKey(NSFontAttributeName) as UIFont

    let italFont = [NSFontAttributeName:UIFont(name: "Georgia-Italic", size: 18.0)]

    var currentColor : UIColor = currentAttributesDict.objectForKey(NSForegroundColorAttributeName) as UIColor

    var currentBGColor : UIColor = currentAttributesDict.objectForKey(NSBackgroundColorAttributeName) as UIColor

    var currentUnderlinedText : UIFont = currentAttributesDict.objectForKey(NSUnderlineStyleAttributeName) as UIFont

    var currentparagraphStyle : NSMutableParagraphStyle = currentAttributesDict.objectForKey(NSParagraphStyleAttributeName) as NSMutableParagraphStyle
}

Upvotes: 0

Views: 1328

Answers (3)

Jeffery Thomas
Jeffery Thomas

Reputation: 42598

You are not testing for nil. objectForKey(_:) returns an optional which you force unwrap (by using as), so if objectForKey(_:) returns nil, then you crash.

You can either keep the values as optionals using as?

var currentColor: UIColor? currentAttributesDict[NSForegroundColorAttributeName] as? UIColor

or you can provide a default value using the ?? operator.

var currentColor: UIColor currentAttributesDict[NSForegroundColorAttributeName] as? UIColor ?? UIColor.blackColor()

NOTE: instead of using objectForKey(_:), you can use []. I think it reads better.

Upvotes: 0

Shuo
Shuo

Reputation: 8937

ObjectForKey will return an optional, you should use as? to cast it to an optional and check its value.

let value = dict.objectForKey("hello") as? String

value is an optional and you can do

if value == nil {}

Or

if let value = dict.objectForKey("hello") as? String {

}

Upvotes: 0

Antonio
Antonio

Reputation: 72770

In all lines like this:

var currentFont : UIFont = currentAttributesDict.objectForKey(NSFontAttributeName) as UIFont

you are extracting a value from a dictionary and doing an explicit cast (to UIFont in this case). All of these lines can fail for any of the following reasons:

  • the specified key doesn't exist in the dictionary, so objectForKey returns nil, and the cast fails
  • the value exists, but it's not of the type you are casting it to, so the cast fails

I don't how you are going to use all these variables, so I cannot provide a proper answer that best solves your problem.

However, you can get rid of the runtime exception by using an optional cast, replacing as with as?. Note that it will turn all the expression results into optionals, so for example in the line of code above, current font would be of UIFont? type:

var currentFont : UIFont? = currentAttributesDict.objectForKey(NSFontAttributeName) as? UIFont

What to do with all these optional variables is up to you: you can use optional binding (but I expect a large number of nested if), or just use them as optionals, if possible.

Upvotes: 1

Related Questions