views:

244

answers:

3

I'm a somewhat competent ruby programmer. Yesterday I decided to finally try my hand with Apple's Cocoa frameworks. Help me see things the ObjC way?

I'm trying to get my head around objc_allocateClassPair and objc_registerClassPair. My goal is to dynamically generate a few classes and then be able to use them as I would any other class. Does this work in Obj C?

Having allocated and registered class A, I get a compile error when calling [[A alloc] init]; (it says 'A' Undeclared). I can only instantiate A using runtime's objc_getClass method. Is there any way to tell the compiler about A and pass it messages like I would NSString? A compiler flag or something?

I have 10 or so other classes (B, C, …), all with the same superclass. I want to message them directly in code ([A classMethod], [B classMethod], …) without needing objc_getClass. Am I trying to be too dynamic here or just botching my implementation? It looks something like this…

 NSString *name = @"test";  
 Class newClass = objc_allocateClassPair([NSString class], [name UTF8String], 0);  
 objc_registerClassPair(newClass);  

 id a = [[objc_getClass("A") alloc] init];  
 NSLog(@"new class: %@ superclass: %@", a, [a superclass]);  
 //[[A alloc] init]; blows up.
+4  A: 

The reason that [[A alloc] init]; blows up is that the compiler has no clue what A means. The compiler never knows that A is even there.

Edit: Also, it looks like what you want is:

@interface A : NSObject {
  NSString *myString;
}

- (id)initWithString:(NSString *)string;

- (void)doItToIt;

@end

or perhaps

@interface NSString (MyPrivateExtension)

- (void)doItToIt;

@end
Williham Totland
Yeah, it seems like going it the normal way works better. In ruby generated classes behave the same way as conventionally declared classes and I was hoping that I might be able to get the same effect here.
kjell_
@kjell_: you do realize that these are two *wildly* different languages, yes?
Williham Totland
Oh, absolutely. But that doesn't stop me from wanting to keep repetitive boilerplate code to a minimum.
kjell_
+1  A: 

When you define a class in the Objective-C language, the compiler defines a new type. When you create a class dynamically, the compiler has no knowledge of that type, so your only choice is to use the class as an id, and send messages to it dynamically. Ruby is a dynamically typed language that likely uses the same mechanisms as the compiler when defining classes at runtime.

pcbeard
A: 

Have a look at the fabulous F-Script and FSClass which can do this and are open source. FSClass defines a meta-class that can be subclassed at runtime.

It does work by using objc_allocateClassPair and objc_registerClassPair but there is alot of other stuff going on (beyond me!) that would probably help.

mustISignUp