3

Let's say I have a generic pointer in objective-c. This pointer could either be a Class object, or it could be an instance of that class. Is there any way to tell the difference between the two?

Example:


id pointerA = [someClass class];
id pointerB = [[someClass alloc] init];

bool pointerAIsAClass = is_this_a_Class(pointerA); // should be true
bool pointerBIsAClass = is_this_a_Class(pointerB); // should be false

How would I write the is_this_a_Class function so that it returns the proper bool value?

bool is_this_a_Class(id somePointer)
{
    // your code goes here
}
Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
e.James
  • 116,942
  • 41
  • 177
  • 214

2 Answers2

4

I don't see a better way, and this isn't foolproof, but this should work:

BOOL pointer_isClass(id object) {
    return [object respondsToSelector:@selector(instancesRespondToSelector:)];
}

Since, theoretically, only Class objects would respond to the -instancesRespondToSelector: message this should work. Outside of an actual objc_* call though I don't see any real API for this.

UPDATE:
After reading Giao's answer another thought came to me, test the pointer's response to the -class method. Calling -class on a class object should be equivalent to calling -self on an object instance but would return another object on an object instance.

BOOL pointer_isClass(id object) {
    return object == [object class];
}

I think this should be more foolproof, especially in the case where an object instance implements -instancesRespondToSelector: this one should work 100% of the time.

Ashley Clark
  • 8,813
  • 3
  • 35
  • 35
  • Beautiful. Your new method works and is much more elegant. Thanks again :) – e.James Dec 10 '08 at 18:16
  • 1
    There's a bunch of useful information about this type of thing here: http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html – Jon Hess Jun 16 '09 at 04:46
  • These answers assume that the methods `class` and `instancesRespondToSelector` are available, which is only true for `NSObject`. Plus, there is no guarantee that a class cannot, for example, override those methods you use above to trick your function. – user102008 Jul 22 '11 at 22:54
3

The most correct way is to check the class of the object, and see if it's a metaclass:

BOOL object_isClass(id object) {
    return class_isMetaClass(object_getClass(object));
}

There are more answers here: Check if object is Class type

Community
  • 1
  • 1
user102008
  • 30,736
  • 10
  • 83
  • 104
  • Cool. That does look like the correct approach. Thank you for taking the time to answer a question from almost three years ago! – e.James Jul 23 '11 at 21:09