Why 'NSUnknownKeyException' Occurs and How to Fix and Prevent It

Learning how to develop on iPhone/iPad can be a painful experience with a steep learning curve, especially if you're new to Objective-C. There are a lot of tools that Apple provide to help lessen this curve, but sometimes beginners bump into problems that are difficult to solve, if only because the error information is less than informative to the uninitiated. An example of this involves the use of XIBs or Storyboards.

With a drag-n-drop UI, Interface Builder simplifies the creation of application screens and is very attractive to those wanting to hit the ground running on this exciting platform. Having taught intro classes for iOS for a couple years now, I can count on one or two people in each of my classes hitting a major barrier in troubleshooting an app that is crashing: the dreaded NSUnknownKeyException.  You'll get console output that looks something like this:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key play.' * First throw call stack: (0x1c91012 0x10cee7e 0x1d19fb1 0xb7ae41 0xafc5f8 0xafc0e7 0xb26b58 0x230019 0x10e2663 0x1c8c45a 0x22eb1c 0xf37e7 0xf3dc8 0xf3ff8 0xf4232 0x433d5 0x4376f 0x43905 0x8eceab6 0x4c917 0x1096c 0x1194b 0x22cb5 0x23beb 0x15698 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x1117a 0x12ffc 0x222d 0x2155) libc++abi.dylib: terminate called throwing an exception (lldb)

What The Problem Is

At runtime your view controller is going to get deserialized from its XIB/Storyboard. During this process, it's going to read all the objects that are in your IB files and start instantiating them with an NSCoder. As it is instantiating those objects in your view, it's going to read the IBOutlet and IBAction connections in your storyboard and start assigning the hydrated objects to those properties that were connected at design time so that you have programmatic access to them at run time. But here's the kicker: If you have a connection that points to a property that doesn't exist, then this exception will be thrown because it was told a property was there that really isn't.

This problem manifests itself most commonly when a connection is created, but the programmer goes into the header and changes the property name. What's happening is that the runtime is expecting to set a property of a given name on your view controller, but that property no longer exists (because you changed it).

How to Fix It

In your storyboard/XIB, right click on the view controller to view its IB connections:

See how there is a connection for the property 'play' and it has a little yellow triangle next to it? This is Interface Builder trying to warn you that you have a connection set there, but the header isn't showing that there is an IBOutlet of that name.

All you need to do is click that little x to break the connection to the missing property.

Additional Resources:

Key-Value Coding Programming Guide

Archives and Serializations Programming Guide

Posted on Jul 8
Written by Wayne Hartman