views:

308

answers:

2

My understanding of IBOutlets is that they act as a marker to ivars and properties in Objective-C classes. Is there anything in the Objective-C runtime that would allow one to query whether an ivar or property or a class has been marked with an IBOutlet at runtime? Or does XCode just do something clever with these at compile time?

If they are a runtime construct, is it possible to define ones own markers and use them in this way:

@private
    MyMarker MyClass instance;
+3  A: 

It is my understanding that Interface Builder simply reads the header files. IBOutlet and IBAction are trivial #defines:

#define IBOutlet
#define IBAction void

that do not affect the compile at all. Interface Builder reads your header files directly (it is notified by Xcode when the header files change, but it just reads and parses the header files itself.

When the nib files are dearchived, the values are set using the ivar or property through the normal interface, but nothing special is noted that the ivar/property is usable by Interface Builder.

So no, the existence of the IBOutlet/IBAction property is not stored and cannot be accessed, nor can you add your own properties.

You could look at attributes and see if there is anything useful that could be attached to the ivar with an attribute, but I'd be very surprised.

Peter N Lewis
+2  A: 

Yes, IBOutlet and IBAction are just thrown away by the parser at the precompilation stage, so there's nothing in the compiled output. And as noted above, they're just textually processed by Interface Builder so that it knows what subset of properties/methods to make available to the connections window.

However, that doesn't stop you doing the same thing yourself - you could just define some #define that are compiled away by the preprocessor, and using textual processing manipulate them. But none of these are available at runtime, which means that you can't really do what you propose.

It's technically possible to write a macro that would do some manipulation of a property/ivar and then add extra information to a different ivar; for example:

#define OUTLET(type,name) type name;BOOL property_##name;
@interface Foo : NSObject
{
        OUTLET(NSString*,foo);
}
@end

would expand to

@interface Foo :NSObject
{
    NSString* foo;
    BOOL property_foo;
}
@end

and you could then use the existence of property_foo to do something with your code (which should be detectable at runtime as well as compile time).

I wouldn't recommend trying to do this generally though ... for a start, it will make your interface (and therefore memory objects) larger than they'd need to be. You'd be better off creating your own class (or struct typedef) to hold the additional information you want.

AlBlue