Objective-C Object as a C Structure
Okay, so figuring out how to unwind an Objective-C object into its base representation goes against all that is object-oriented programming, however, it’s interesting none-the-less.
In Objective-C there is a directive, @defs(), that outputs (at compile time) the list of instance variables for a class. We can use this list to create a C structure with the variables of a specified class.
For instance, if we have a class named TestClass, here is how one might create a structure using the @defs directive:
1 2 3 4 | struct testClassStructure { @defs(TestClass); } *testClassAsStruct; |
Before we look at how to use this structure to access the variables of TestClass, let’s look at a simple interface and implementation of TestClass:
TestClass Interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // TestClass.h #import <UIKit/UIKit.h> @interface TestClass : NSObject { NSString *testString; int testInteger; BOOL testBoolean; } @property (nonatomic, retain) NSString *testString; @property (readonly) int testInteger; @property BOOL testBoolean; @end |
TestClass Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // TestClass.m #import "TestClass.h" /*------------------------------------- * TestClass implementation *-------------------------------------*/ @implementation TestClass @synthesize testString; @synthesize testInteger; @synthesize testBoolean; - (id)init { if (self = [super init]) { testString = [[NSString alloc] initWithString:@"Fubar"]; testInteger = 99; testBoolean = YES; } return self; } - (void)dealloc { [testString release]; [super dealloc]; } @end |
Pretty simple stuff. Our interface defines three instance variables, a string, an integer and a boolean. The implementation file, upon initialization of a TestClass object sets defaults values for each instance variable.
So, let’s look at how to use a C structure to read/write the instance variables of TestClass:
AppDelegate Interface
1 2 3 4 5 6 7 8 9 10 11 12 | // UntitledAppDelegate.h #import <UIKit/UIKit.h> @interface UntitledAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; } @property (nonatomic, retain) IBOutlet UIWindow *window; @end |
AppDelegate Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | // UntitledAppDelegate.m #import "UntitledAppDelegate.h" #import "testClass.h" @implementation UntitledAppDelegate @synthesize window; struct testClassStructure { @defs(TestClass); } *testClassAsStruct; - (void)applicationDidFinishLaunching:(UIApplication *)application { TestClass *tmp; tmp = [[TestClass alloc] init]; testClassAsStruct = (struct testClassStructure *) tmp; NSLog(@"testString: %@", testClassAsStruct->testString); NSLog(@"testInteger: %d", testClassAsStruct->testInteger); NSLog(@"testBoolean: %s", testClassAsStruct->testBoolean == YES ? "Yes" : "No"); testClassAsStruct->testString = @"A new string"; testClassAsStruct->testInteger = 0; testClassAsStruct->testBoolean = NO; NSLog(@"testString: %@", testClassAsStruct->testString); NSLog(@"testInteger: %d", testClassAsStruct->testInteger); NSLog(@"testBoolean: %s", testClassAsStruct->testBoolean == YES ? "Yes" : "No"); [tmp release]; } - (void)dealloc { [window release]; [super dealloc]; } @end |
And of course, the output:

There you have it. An inside look at how to work with an Objective-C object using a C structure. I imagine there is a good use case for this, I’m just not sure I know what it is…if you can think of one, please post a comment.
Related posts:



Maybe quick and dirty serialization?
[Reply]
Actually, unless you use the @private: or @protected: declarations to explicity hide the instance variables, the compiler will do all this for you automatically. Try it by using tmp->testString, etc. in the above code.
[Reply]
Could I use methods in this way (from structure)?
eg. testClassAsStruct->mypreviouslyDeclaredMethod()
If no, I would ask by the way, maybe you know if it is possible at all in ObjC/iPhone to call methods with dot syntax, so like this:
myClass.myMethod(var)
[Reply]
“I imagine there is a good use case for this, I’m just not sure I know what it is…if you can think of one, please post a comment.”
In a role playing game the player drinks a potion displayed as a colored bottle.
Your stats change accordingly.
POTION is your Testclass
it contains
int deltastrenght = 5;
int deltastamina = -2;
int effectsduration = 10;
bool hasEffectOnElves = NO;
And the main class of your game register those values when the player drinks that potion.
[Reply]
Instance variables are @protected by default—what James Yopp said is incorrect. If you mark them as @public you can automatically do the above though. You also can access self as a struct pointer.
[Reply]