4

I am using performSelector:, which returns an id object, to call several other methods. The return type of those methods can actually be either be a BOOL, int, NSDate or any other kind of object.

How can I figure out whether the object returned from performSelector: is a BOOL or not? I tried converting it to a NSNumber and such, but this crashes if the object is not a BOOL.

I have a class with attributes such as these:

@property(retain,nonatomic) NSString* A;
@property(assign,nonatomic) BOOL B;
@property(retain,nonatomic) NSArray* C;
@property(assign,nonatomic) int64_t D;

This class is generated by a framework, so I cannot change it. But I want to loop over A, B, C, D to call each attribute and retrieve the data. However, as you can see, the return type can vary and I need to adjust to that.

I am doing something similar to:

SEL s = NSSelectorFromString(@"A");
id obj = [object performSelector:s];
//check if obj is BOOL
//do something with obj
jscs
  • 63,694
  • 13
  • 151
  • 195
Se7enDays
  • 2,543
  • 2
  • 17
  • 22

1 Answers1

9

If all you need to do is obtain the values of various properties, use key-value coding, which automatically wraps scalar types such as int and BOOL in instances of NSNumber. So all you would need would be a line like the following:

id value = [object valueForKey:@"somePropertyName"];

Otherwise, you could check ahead of time for the return type by calling methodSignatureForSelector: on the target object, but that seems like a bunch of unnecessary work given the situation you described.

jlehr
  • 15,557
  • 5
  • 43
  • 45
  • 2
    Moreover, you _can't_ use `performSelector:` for a non-object return type. As [its docs say:](http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/doc/uid/20000052-BBCBGHFG) "For methods that return anything other than an object, use NSInvocation." – jscs Jan 22 '13 at 19:21
  • @JoshCaswell *Can't* might be too strong a word, as it's possible to use `performSelector:` to invoke a method that returns a scalar value and then cast the result to the appropriate type, but it's clearly not intended for that use, so in general you *shouldn't*. – jlehr Jan 22 '13 at 20:57
  • Such a cast is not guaranteed to get you the value you expect (depending on ABI): http://www.cocoabuilder.com/archive/cocoa/288663-bool-returned-via-performselctor-not-bool-on-64-bit-system.html, http://www.red-sweater.com/blog/320/abusing-objective-c-with-class (see especially the link to Greg Parker's post) and won't work at all for floats or structs. – jscs Jan 22 '13 at 21:10
  • Right, which is why you really, really *shouldn't*. ;-) – jlehr Jan 22 '13 at 21:19