Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Weird coding-compliant error

I'm having a problem and I couldn't find anyone else on the web with the same struggle, maybe it's just too silly.

I have the following class:

class UIXOColourPicker : UIView {
    @IBInspectable var moodValue: Int!
    ...
}

And in my storyboard I have a view just like this:

enter image description here

The user defined runtime attribute was generated by Xcode IBInspectable functionality (which is really cool btw), but whenever I try to run the app I get the error

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIXOColourPicker 0x7fa86877c420> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key moodValue.'

I'm on Xcode 6 - Beta 6.

Any ideas?

Sorry if it's a silly question, but I've been struggling with it for like 2 hours and I don't have any other Swift developer here to have a look at it.

Cheers

like image 224
Marcos Duarte Avatar asked Aug 21 '14 15:08

Marcos Duarte


2 Answers

@IBInspectable uses cocoa objects and not native swift types. So, anything that isn't implicitly convertible to a swift type needs to be a cocoa object instead. For Number or Bool you'd need NSNumber. For something like Point, Size, Rect, etc, you'd need to use NSValue. However, for String you can use String directly; you don't need to use NSString.

So, in your case, you need to use NSNumber instead of Int. I'd also use NSNumber? instead of NSNumber! in case the value isn't set in your storyboard/xib.

@IBInspectable var moodValue: NSNumber?

Update

As @JakeLin and @Echelon pointed out, for int like values, Xcode will only show the attribute in the Attributes Inspector if you declare it as an Int?, but then it will crash at runtime. If you use an NSNumber?, it won't crash at runtime, but the attribute won't be available in the Attributes Inspector anymore; it will only show up in the User Defined Runtime Attributes (this seems like a bug in Xcode to me).

The error itself tells us how to get around that problem though:

IBInspectable[66994:58722469] Failed to set (moodValue) user defined inspected property on (q25429792___IBInspectable.ViewController): [ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key moodValue.

What this is saying is that the runtime can't find a "key value coding-compliant" attribute on the class for moodValue (Int attributes aren't key value coding-compliant) and that you can implement setValue:forUndefinedKey: to fix that.

In that case, the implementation might look something like this:

@IBInspectable var moodValue: Int?

override func setValue(value: AnyObject?, forUndefinedKey key: String) {
    if let value = value as? Int? where key == "moodValue" {
        self.moodValue = value
    }
}

So, if you really want the attribute to show up in the Attributes Inspector and you don't mind adding the extra method, declare your property as an Int? and implement setValue:forUndefinedKey:. If you don't want the extra method, you'll have to content yourself with using an NSNumber? and the User Defined Runtime Attributes UI.

like image 114
Mike S Avatar answered Oct 17 '22 09:10

Mike S


This is down to your type for moodValue. It seems the KVO system can't handle the type coercion needed; it's looking for a moodValue with the actual type NSNumber. Changing

@IBInspectable var moodValue: Int!

to

@IBInspectable var moodValue: NSNumber!

Then picking out the moodValue.integerValue should do what you want.

like image 29
Adam Wright Avatar answered Oct 17 '22 11:10

Adam Wright