Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Unknown class <MyClass> in Interface Builder file" error at runtime

Despite the "Unknown class MyClass in Interface Builder file." error printed at runtime, this issue has nothing to do with Interface Builder, but rather with the linker, which is not linking a class because no code uses it directly.

When the .nib data (compiled from the .xib) is loaded at runtime, MyClass is referenced using a string, but the linker doesn't analyze code functionality, just code existence, so it doesn't know that. Since no other source files references that class, the linker optimizes it out of existence when making the executable. So when Apple's code tries to load such a class, it can't find the code associated with it, and prints the warning.

By default, Objective-C targets will have -all_load -ObjC flags set by default, which will keep all of the symbols. But I had started with a C++ target, and didn't have that. Nevertheless, I found a way around this, which keeps the linker aggressive.

The hack I was originally using was to add an empty static routine like:

+(void)_keepAtLinkTime;

which does nothing, but that I would call once, such as:

int main( int argc, char** argv )
{
   [MyClass _keepAtLinkTime];
   // Your code.
}

This would force the linker to keep the whole class, and the error disappears.

As jlstrecker pointed out in the comments, we do not really need to add a _keepAtLinkTime method. Simply calling an existing one, such as:

   [MyClass class];

does the trick (as long as you derive from an NSObject).

Of course, you can call this in any location of your code. I guess it could even be in unreachable code. The idea is to fool the linker into thinking that MyClass is used somewhere so that it isn't so aggressive in optimizing it out.

Xcode 6.3.2 & Swift 1.2

Swift definition of view. Be sure to override init(coder aDecoder: NSCoder). Objective-C definition of view controller. And, a nib in a pear tree.

Add Module Name to Nib details inspector where you pick your class.


I fixed this along the lines of what Laura suggested but I didn't need to recreate the files.

  • Using XCode 4, in the Project Navigator, select the .m file that contains the class that it is complaining about

  • Go to View->Utilities->Show File Inspector
    (this will show the File Inspector to the right, with that .m-file info)

  • Open the Target Membership section and make sure that your target is selected for this .m-file

When I added my .m file to my project, it didn't add it to my default target for some reason and that caused me to get the error you mentioned.


This doesn't really have anything to do with Interface Builder, what's happening here is the symbols aren't being loaded from your static library by Xcode. To resolve this problem you need to add the -all_load -ObjC flags to the Other Linker Flags key the Project (and possibly the Target) Build Settings.

Since Objective-C only generates one symbol per class we must force the linker to load the members of the class too by using the -ObjC flag, and we must also force inclusion of all our objects from our static library by adding the -all_load linker flag. If you skip these flags sooner or later you will run into the error of unrecognized selector or get other exceptions such as the one you've observed here.


I did run into this problem today using Swift.

I changed a class Model.h + Model.m to a Model.swift. This object was used in Interface Builder with the class = Model.

As soon as I replaced the object the class could no longer be loaded.

What I had to do was to change the class reference in IB from:

Class = Model
Module = 

to

Class = Model
Module = <TARGETNAME>

You'll find the <TARGETNAME> in the build settings. It is also the name that shows up in your generated Swift-Header: #import "TARGETNAME-Swift.h"