views:

221

answers:

4

Say I have my class

@interface Person : NSObject { NSString *name; }

I need to get the name of NSString's within my class

Person *person = [[Person alloc] init];
NSLog(@"Name of variable %s\n", _NameofVariable_(person->name));

Thanks for the answers, here's the solution I came up from the replies

//returns nil if property is not found
-(NSString *)propertyName:(id)property {  
    unsigned int numIvars = 0;
    NSString *key=nil;
    Ivar * ivars = class_copyIvarList([self class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        if ((object_getIvar(self, thisIvar) == property)) {
            key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            break;
        }
    } 
    free(ivars);
    return key;
}  
A: 

If the person object is exposed as a property of the class, you can use objc_msgSend to get the value.

So, if you could access person using

[object person]

You could also do

objc_msgSend(object, "person")

For more details on message sending, including how to pass arguments to methods, see the Objective-C Runtime Programming Guide section on Messaging

Robert Christie
A: 

Possibly the answers to this question might be of use to you.

calmh
+2  A: 

You can get the names of a class's instance variables with the Objective-C runtime API function class_copyIvarList. However, this is rather involved, rarely done and almost never the best way to accomplish something. If you have a more specific goal in mind than mere curiosity, it might be a good idea to ask about how to accomplish it in Objective-C.

Also, incidentally, person.name doesn't specify an instance variable in Objective-C — it's a property call. The instance variable would be person->name.

Chuck
I didn't know you could access instance variables that way. Will likely never use it, but good to know.
Brandon Bodnár
@Brandon you can do that because Objective-C objects are really just structs. :)
Dave DeLong
@Dave​​​​​, Doh!​​​​​
Brandon Bodnár
+1  A: 

You might use preprocessor stringification and a bit of string twiddling:

NSUInteger lastIndexAfter(NSUInteger start, NSString *sub, NSString *str) {
    NSRange found = [str rangeOfString:sub options:NSBackwardsSearch];
    if(found.location != NSNotFound) {
        NSUInteger newStart = NSMaxRange(found);
        if(newStart > start)
            return newStart;
    }
    return start;
}

NSString *lastMember(NSString *fullName) {
    if(!fullName) return nil;

    NSUInteger start = 0;
    start = lastIndexAfter(start, @".", fullName);
    start = lastIndexAfter(start, @"->", fullName);

    return [fullName substringFromIndex: start];
}

#define NSStringify(v) (@#v)
#define _NameofVariable_(v) lastMember(NSStringify(v))
Chris Johnsen