PDA

View Full Version : Storing a class in a Cocoa collection?




Nutter
Feb 25, 2007, 06:58 AM
Does anybody know a good way to to store the Class type (as returned by +class) in a Cocoa collection?

The best solution I can think of is to create a simple object wrapper to store the variable ... is there a better way?



HiRez
Feb 25, 2007, 07:18 AM
Does anybody know a good way to to store the Class type (as returned by +class) in a Cocoa collection?

The best solution I can think of is to create a simple object wrapper to store the variable ... is there a better way?You could do that, but since each object can retrieve its own class, as you pointed out above, why do you need to store it separately? Just retrieve objects into an id object and call the +class method on the objects in the collection to find out what they are. And use the NSStringFromClass() if you need a string for the class name.

kainjow
Feb 25, 2007, 09:19 AM
No need to convert to NSString or write a wrapper. It should work just like a standard object:

NSMutableArray *array = [NSMutableArray array];
[array addObject:[NSString class]];
[array addObject:[NSArray class]];
[array addObject:[NSDictionary class]];
[array addObject:[NSData class]];
[array addObject:[NSNumber class]];

Nutter
Feb 25, 2007, 12:17 PM
No need to convert to NSString or write a wrapper. It should work just like a standard object.

But surely that won't work, will it? Won't the collection attempt to retain the object that I'm adding, causing a crash as there is no class method called "retain"?

I must admit I haven't actually tried this, I just assumed it wouldn't work!

You could do that, but since each object can retrieve its own class, as you pointed out above, why do you need to store it separately? Just retrieve objects into an id object and call the +class method on the objects in the collection to find out what they are. And use the NSStringFromClass() if you need a string for the class name.

But I'm not storing any objects, only the classes. It's probably quite an unusual case - I want to store a list of classes associated with particular dictionary keys, so that I can later read a second dictionary and check that the stored objects are of the right class.

kainjow
Feb 25, 2007, 01:23 PM
I must admit I haven't actually tried this, I just assumed it wouldn't work!

Well try it ;)

Nutter
Feb 25, 2007, 01:37 PM
My god, it works! I am impressed. My only remaining question is ... how??

wittegijt
Feb 25, 2007, 03:12 PM
My god, it works! I am impressed. My only remaining question is ... how??

[MyClass class] returns the class object. In obj-C a class is also an object (unlike C++). Since it is an object, you can store it in an array. There really is nothing special about it.
See http://www.blackbagops.net/?p=83 for more info on class objects.

Wittegijt

Nutter
Feb 25, 2007, 04:19 PM
[MyClass class] returns the class object. In obj-C a class is also an object (unlike C++). Since it is an object, you can store it in an array. There really is nothing special about it.

I do understand that, I'm just wondering why the runtime doesn't raise an exception when trying to call the method retain on the class object. Is there a (dummy) class method declared by NSObject called retain? If so, it's not documented. Am I missing something?

Thanks for the link by the way.

wittegijt
Feb 25, 2007, 06:01 PM
I do understand that, I'm just wondering why the runtime doesn't raise an exception when trying to call the method retain on the class object. Is there a (dummy) class method declared by NSObject called retain? If so, it's not documented. Am I missing something?

Thanks for the link by the way.

I'm afraid I don't understand what the problem is. Why would the runtime raise an exception?
BTW: The NSObject protocol does declare retain.

Wittegijt

Nutter
Feb 26, 2007, 03:35 AM
The NSObject protocol declares retain as an instance method, not a class method! Or at least it appears to...

The runtime raises an exception when you send a message to a method that doesn't exist. Try it yourself - find one of your own objects, and send a message to invoke an instance method to the class. For example:

[FooClass doFoo];

You will get an exception. However, attempt to call any instance method declared by NSObject and nothing will happen:

[FooClass retain];

Why is that? Is NSObject declaring every single one of these methods as class methods as well?

wittegijt
Feb 26, 2007, 04:54 AM
The NSObject protocol declares retain as an instance method, not a class method! Or at least it appears to...

The runtime raises an exception when you send a message to a method that doesn't exist. Try it yourself - find one of your own objects, and send a message to invoke an instance method to the class. For example:

[FooClass doFoo];

You will get an exception. However, attempt to call any instance method declared by NSObject and nothing will happen:

[FooClass retain];

Why is that? Is NSObject declaring every single one of these methods as class methods as well?

Of course it's an instance method! What would be the use of reference counting a class? There will be only one class object for every class, no? And the [MyClass class] method returns an instance, not a class object!

Wittegijt

Nutter
Feb 26, 2007, 05:03 AM
No, [MyClass class] returns a pointer to the class object itself.

I've found the answer: "Instance methods defined in the root class can be performed both by instances and by class objects." (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/index.html#//apple_ref/doc/uid/TP40002974)

It's annoying that Apple doesn't mention this in the NSObject reference.

wittegijt
Feb 26, 2007, 05:15 AM
Ok, good find. Thanks.

Wittegijt

Krevnik
Feb 26, 2007, 03:12 PM
No, [MyClass class] returns a pointer to the class object itself.

I've found the answer: "Instance methods defined in the root class can be performed both by instances and by class objects." (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/index.html#//apple_ref/doc/uid/TP40002974)

It's annoying that Apple doesn't mention this in the NSObject reference.

Although, intuitively, this makes a lot of sense.

Instances are objects that follow the protocol laid out by the class. Class objects are also objects, that follow the protocol laid out by the runtime. Class objects can be retained and released, as they are simply objects. But, there might be special behavior so that only the runtime can actually cause a class object to be deallocated. If not, you might be able to have fun crashing an app with:

[[NSObject class] release];

When dealing with Obj-C, I find it is better if I think in the Java/C# mindset than the C++ mindset. Objective-C provides a very robust runtime that C++ never thought about providing (since it was a OOP hack onto C to 'go where the business was wanting to go').