问题
1) object_getIvar(id object, Ivar ivar) returns an 'id' if the Ivar is an object eg. if the variabe is an NSString, presumably the id = NSString which contains the value. Is that correct? Or what do I need to do to access the value of the Ivar.
2) if the Ivar is a float/int etc. what will get returned and how do I convert it into something I can use (a float or int is fine as I can use NSNumber numberWithXXX to convert it to an object).
回答1:
1) Correct. As stated by the docs:
Return Value
The value of the instance variable specified by ivar, or nil if object is nil.
2) No matter the type of the Ivar you will always get the value that the Ivar holds. You can determine the type of the Ivar by using ivar_getTypeEncoding. There's a list of the various type encodings here.
With that information at hand, you should be able to write a switch that handles each case appropriately; e.g.:
(warning: non-tested code ahead)
const char* typeEncoding = ivar_getTypeEncoding(var);
switch (typeEncoding) {
case '@': {
// handle class case
} break;
case 'i': {
// handle int case
} break;
case 'f': {
// handle float case
} break;
// .. and so on
}
回答2:
Example use for printing the description of arbitrary objects:
- (NSString *) qCustomDescription
{
static int depth = 0;
NSMutableString *resultString = [NSMutableString stringWithFormat: @"<%@: %p>", NSStringFromClass([self class]), self];
uint32_t ivarCount;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
if( ivars )
{
++depth;
[resultString appendString: @"\n"];
for( int tabs = depth; --tabs > 0; )
[resultString appendString: @"\t"];
[resultString appendString: @"{"];
for( uint32_t i = 0; i < ivarCount; ++i )
{
Ivar ivar = ivars[i];
const char* type = ivar_getTypeEncoding(ivar);
const char* ivarName = ivar_getName( ivar );
NSString* valueDescription = @"";
NSString* name = [NSString stringWithCString: ivarName encoding: NSASCIIStringEncoding];
switch( type[0] )
{
case '@':
{
id v = object_getIvar(self, ivar);
if( v )
{
if( [self respondsToSelector: @selector(qDescriptionForValue:)] )
valueDescription = [self performSelector: @selector(qDescriptionForValue:) withObject: v];
else
valueDescription = [v description];
}
break;
}
case 'c':
{
char v = ((char (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%c", v];
break;
}
case 'i':
{
int v = ((int (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%i", v];
break;
}
case 's':
{
short v = ((short (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%d", v];
break;
}
case 'l':
{
long v = ((long (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%ld", v];
break;
}
case 'q':
{
long long v = ((long long (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%lld", v];
break;
}
case 'C':
{
unsigned char v = ((unsigned char (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%uc", v];
break;
}
case 'I':
{
unsigned int v = ((unsigned int (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%u", v];
break;
}
case 'S':
{
unsigned short v = ((unsigned short (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%u", v];
break;
}
case 'L':
{
unsigned long v = ((unsigned long (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%lu", v];
break;
}
case 'Q':
{
unsigned long long v = ((unsigned long long (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%llu", v];
break;
}
case 'f':
{
float v = ((float (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%f", v];
break;
}
case 'd':
{
double v = ((double (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%f", v];
break;
}
case 'B':
{
BOOL v = ((BOOL (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%@", v ? @"YES" : @"NO"];
break;
}
case '*':
{
char *v = ((char* (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"%s", v];
break;
}
case '#':
{
id v = object_getIvar(self, ivar);
valueDescription = [NSString stringWithFormat: @"Class: %s", object_getClassName(v)];
break;
}
case ':':
{
SEL v = ((SEL (*)(id, Ivar))object_getIvar)(self, ivar);
valueDescription = [NSString stringWithFormat: @"Selector: %s", sel_getName(v)];
break;
}
case '[':
case '{':
case '(':
case 'b':
case '^':
{
valueDescription = [NSString stringWithFormat: @"%s", type];
break;
}
default:
valueDescription = [NSString stringWithFormat: @"UNKNOWN TYPE: %s", type];
break;
}
[resultString appendString: @"\n"];
for( int tabs = depth; --tabs >= 0; )
[resultString appendString: @"\t"];
[resultString appendFormat: @"%@: %@", name, valueDescription];
}
[resultString appendString: @"\n"];
for( int tabs = depth; --tabs > 0; )
[resultString appendString: @"\t"];
[resultString appendString: @"}"];
--depth;
free(ivars);
}
return resultString;
}
来源:https://stackoverflow.com/questions/1216262/handling-the-return-value-of-object-getivarid-object-ivar-ivar