How to know if Objective C pointer is of `Class` type? - objective-c

I would like to know if a pointer in my program is pointing to a Class type.
Something like:
if ([anObject isKindOfClass:[Class class]]])
This an error because [Class class] does not exist.
The closet I can come to is this:
NSLog(#"Will run");
const char *nameOfClass = class_getName(#"DoesNotExist");
if (nameOfClass == NULL || (strlen(nameOfClass) == 0)
{
NSLog(#"Not a class");
} else {
NSLog(#"String: %s", nameOfClass);
}
NSLog(#"Did run");
Where an empty const char *nameOfClass would tell me that it isn't in fact a Class object. Any other ideas?

There's an Obj-C runtime function called object_isClass.
#import <objc/runtime.h>
if (object_isClass(anObject))
Another valid approach would be to use class_isMetaClass(object_getClass(anObject)), since the class of a class is a metaclass.

Related

Correct way to find out all the superclasses of a Class in Objective-C?

I'm a novice, and I seem to be getting multiple errors on this.
All I want is a for or while loop to print out all the superclasses of a certain Class.
Here is the pseudocode of what I want:
IDontKnowWhatClass *superClassName;
while (superClassName != nil)
{
superClassName = [[superClassName class] superclass];
NSLog(print the name);
}
Try this
Class superClassName = [self class];
while (superClassName != nil)
{
superClassName = [superClassName superclass];
NSLog(#"%#",NSStringFromClass(superClassName));
}
If you know a class itself like NSString then,
Class superClassName = [NSString class];
You can store the class name to a string like
NSString *className = NSStringFromClass(superClassName);
And if you want to create an object of the class from which class name is stored in a string like
id object = [[NSClassFromString(className) alloc] init];
Use NSObject method names as :
objc_property_t class_getProperty(Class cls, const char *name)
//Returns a property with a given name of a given class.
Keep on finding till you get the NSObject as it is supermost class
Use this method to check for equality :
- (BOOL)isEqual:(id)object;
or
[object isKindOfClass:[SomeClass class]]
Documentation here
This will work
You can call superclass method on your current class until it gets equal to Nil (that will happen for root class, i.e. NSObject).
Class c = [IDontKnowWhatClass class];
while (c)
{
NSLog(#"%#", NSStringFromClass(c));
c = [c superclass];
}
NSString* classString = #"IDontKnowWhatClass";
Class class = NSClassFromString(classString);
while (class != nil){
NSLog(#"%#", [class description]);
class = [class superclass];
}

Function calls with pointers in Objective C

I'm a newbie in Objective C, used to write C. Anyway, I have a class called DataProcessing:
DataProcessing.m
...
- (BOOL)MyStringTweaker:(NSString *)strIn : (NSString *)strOut {
if(some_thing) {
strOut = [NSString stringWithFormat:#"I_am_tweaked_%#", strIn];
return true;
}
else
return false;
}
...
From the AppDelegate (OSX Application)
AppDelegate.m
...
NSString *tweaked;
DataProcessing *data_proc = [[DataProcessing alloc] init];
if([data_proc MyStringTweaker:#"tweak_me":tweaked])
NSLog([NSString stringWithFormat:#"Tweaked: %#", tweaked]);
else
NSLog(#"Tweaking failed...");
...
This doesn't work, *tweaked is NIL after the call to MyStringTweaker...
What am I missing?
Objective-C, like C, is pass-by-value only. You need to change your method signature to be:
- (BOOL)MyStringTweaker:(NSString *)strIn : (NSString **)strOut
and use:
*strOut = [NSString stringWithFormat:#"I_am_tweaked_%#", strIn];
to do the assignment.
Then, where you call it, you need to pass the address of the pointer you want to fill in:
[data_proc MyStringTweaker:#"tweak_me" :&tweaked]
A good explanation is in the comp.lang.c FAQ.
Editorial aside: Why not label the second argument? It looks weird to have it naked like that.

pointer before declaration of object objective-c

can you tell me something : is it a mistake or can we write "result" without the " * " here :
#implementation Person (Sorting)
- (NSComparisonResult)compareByName:(Person *)person2 {
>>//here :
>>NSComparisonResult result = [self.lastName caseInsensitiveCompare:person2.lastName];
if (result == NSOrderedSame) {
return [self.firstName caseInsensitiveCompare:person2.firstName];
}
return result;
}
#end
Thanks
caseInsensitiveCompare method returns NSComparisonResult so not using * is absolutely correct.
In objective-c you must use pointers to obj-c objects, but NSComparisonResult is just an enum (i.e. plain integer) so you may freely use it without pointer.

Multiple methods warning

I'm currently learning Objective C and in the process I've made the silly little program below. The program compiles fine - however I get the warning "multiple methods named '-setName:' found".
I've only interfaced and implemented the method once.
What does this warning mean, and how do I correct it?
#import <Foundation/Foundation.h>
// these are the three yoga-exercises we can perform
typedef enum {
kCobra,
kUniversal,
kDog
} ExerciseName;
// translating our variables into human
NSString *nameExercise (ExerciseName nameExercise)
{
switch (nameExercise) {
case kCobra:
return #"Cobra Pose";
break;
case kUniversal:
return #"Universal Stretch";
break;
case kDog:
return #"Dog Pose";
break;
}
return #"no clue!";
} // nameExercise
#interface Exercise : NSObject
{
ExerciseName name;
}
-(void) setName: (ExerciseName) name;
-(void) exerciseDo;
#end
#implementation Exercise
-(void) setName: (ExerciseName) n {
name = n;
} // setName
-(void) exerciseDo {
NSLog(#"Exercise: %#",
nameExercise(name));
}
#end
void executeExercises(id exercises[], int count) {
int i;
for(i=0; i<count; i++) {
id exercise = exercises[i];
[exercise exerciseDo];
}
}
int main (int argc, const char * argv[]) {
id exercises[1];
exercises[0] = [Exercise new]; // initiating an object of class Exercise
[exercises[0] setName:kDog];
executeExercises(exercises, 1);
return 0;
} //main
the meaning of the message is that there are multiple selectors with the name setName: in the translation (that is, it is declared in at least on other place among all included headers). the compiler may choose the wrong selector (which can introduce undefined behavior).
you can typically correct the problem using one (or more) of the following approaches:
1) rename the method to a unique name: e.g. setExerciseName may be ok, if not used in other translations.
2) match the signature of the other selector. e.g. setName:(NSString *)name
3) use type safety:
Exercise * ex = [Exercise new];
[ex setName:kCobra];
4) cast the variable to the type: [(Exercise*)exercise setName:kCobra];
5) restore the type with a new variable: Exercise * ex = exercise;
since you have declared the var as an id, you have erased the type, and it means that the object may respond any visible selector. in general, you should not erase the type in this manner, except when truly necessary.
the best approach i see is a combination of 1 and 3:
[ex setExerciseName:kCobra];

How can I know whether an instance implements a method in Objective-C?

I would like to know if an instance implements a specific method. I could use respondsToSelector: but it returns YES if the instance inherits the method...
I could loop through the methods of class_copyMethodList(), but since I might want to check a lot of instances, I wanted to know if there was a simpler solution (like repondsToSelector:, but restricted to the class itself...)
edit: since I really think there is no function or method doing that, I wrote mine. Thanks for your answers, here is the method if it can be of any use :
+ (BOOL)class:(Class)aClass implementsSelector:(SEL)aSelector
{
Method *methods;
unsigned int count;
unsigned int i;
methods = class_copyMethodList(aClass, &count);
BOOL implementsSelector = NO;
for (i = 0; i < count; i++) {
if (sel_isEqual(method_getName(methods[i]), aSelector)) {
implementsSelector = YES;
break;
}
}
free(methods);
return implementsSelector;
}
It's probably easier to check whether the method your own class returns is the same or different than the method your superclass returns.
if ([[obj class] instanceMethodForSelector:sel] != [[obj superclass] instanceMethodForSelector:sel]) {
NSLog(#"%# directly implements %#", [obj class], NSStringFromSelector(sel));
}
instance responds and super does not:
-(BOOL) declaresSelector:(SEL)inSelector {
return [self respondsToSelector:inSelector] && ![super respondsToSelector:inSelector];
}
instance responds and is different than super:
-(BOOL) implementsSelector:(SEL)inSelector {
return [self respondsToSelector:inSelector] && !( [super respondsToSelector:inSelector] && [self methodForSelector:inSelector] == [super methodForSelector:inSelector] );
}
According to Apple documents you should call respondsToSelector before methodForSelector.
You can use reflection to do that.