Swift - Weird coding-compliant error
Asked Answered
C

2

9

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

Classical answered 21/8, 2014 at 15:5 Comment(0)
M
14

@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.

Moose answered 21/8, 2014 at 15:35 Comment(3)
@IBInspectable doesn't support NSNumber, it won't show up in Interface Builder.Orchid
I am really confused by this. @JakeLin is correct - when set to NSNumber, my @IBInspectables don't show up in the Attributes Inspector (only the raw key paths in the User Defined Runtime Attributes). When I use Int, they do show up, but they throw runtime exceptions.Martres
@Martres and @JackLin, I updated the answer with a different workaround that lets you use Int so that it'll show up in the Attributes Inspector.Moose
C
6

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.

Cracksman answered 21/8, 2014 at 15:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.