If you see this warning:
warning: receiver 'MyCoolClass' is a forward class and corresponding @interface may not exist
you need to #import
the file, but you can do that in your implementation file (.m), and use the @class
declaration in your header file.
@class
does not (usually) remove the need to #import
files, it just moves the requirement down closer to where the information is useful.
For Example
If you say @class MyCoolClass
, the compiler knows that it may see something like:
MyCoolClass *myObject;
It doesn't have to worry about anything other than MyCoolClass
is a valid class, and it should reserve room for a pointer to it (really, just a pointer). Thus, in your header, @class
suffices 90% of the time.
However, if you ever need to create or access myObject
's members, you'll need to let the compiler know what those methods are. At this point (presumably in your implementation file), you'll need to #import "MyCoolClass.h"
, to tell the compiler additional information beyond just "this is a class".
There is also an easier way to access the view instead of dealing with the nib as an array.
1) Create a custom View subclass with any outlets that you want to have access to later. --MyView
2) in the UIViewController that you want to load and handle the nib, create an IBOutlet property that will hold the loaded nib's view, for instance
in MyViewController (a UIViewController subclass)
@property (nonatomic, retain) IBOutlet UIView *myViewFromNib;
(dont forget to synthesize it and release it in your .m file)
3) open your nib (we'll call it 'myViewNib.xib') in IB, set you file's Owner to MyViewController
4) now connect your file's Owner outlet myViewFromNib to the main view in the nib.
5) Now in MyViewController, write the following line:
[[NSBundle mainBundle] loadNibNamed:@"myViewNib" owner:self options:nil];
Now as soon as you do that, calling your property "self.myViewFromNib" will give you access to the view from your nib!
Best Answer
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:
which does nothing, but that I would call once, such as:
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: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.