views:

999

answers:

3

I have a method that receives many different kinds of objects and decides what to do with them:

-(void)performAction:(NSObject *)myAction withItem:(Item *)myItem {

actionCount = -1;
NSLog(@"-- NEW ACTION ARRAY --");
if ([myAction isMemberOfClass:[Look class]]) {
 currentActionArray = [self createLookArray:(Look *)myAction item:myItem];
} else if ([myAction isMemberOfClass:[Use class]]) {
 currentActionArray = [self createUseArray:(Use *)myAction item:myItem];
} else if ([myAction isMemberOfClass:[Exit class]]) {
 currentActionArray = [self createExitArray:(Exit *)myAction item:myItem];
} else if ([myAction isMemberOfClass:[NSArray class]] ) {
 NSLog(@"--- CUSTOM ACTION --- %@", myAction);
 currentActionArray = (NSArray *)myAction;
} 
[self performNextAction];

}

One of four things is going to come through here: Look, Use, Exit or NSArray. The first three are sent off to become NSArrays, the last is already an NSArray.

Now, when I do pass an NSArray in here from elsewhere, like this:

    NSArray *myAction = [[NSArray alloc] initWithObjects:myAction1, myAction2, nil];
[controller performAction:myAction withItem:nil];

...the custom action is never called, because it reads myAction as an NSCFArray rather than an NSArray. When I try [myAction isMemberOfClass:[NSCFArray class]] it doesn't recognise the CF. The simple way to get it working at the moment is just to assume that anything not a Look, Use or Exit is an NSArray (get rid of the last else if, and just leave it as an else), but that seems sloppy to me.

Anyone know how I can deal with this?

Thanks, -k.

+7  A: 

You can try using isKindOfClass: instead of isMemberOfClass:.

The first one will return YES for objects that are either instances of the class you send, or subclasses of it, as it may be the case for NSCFArray.

pgb
That did it. Forgot about that one. Thanks all.
Kevin Beimers
I think it is important to note that `NSArray`, `NSString` and many other classes are _class clusters_. Meaning that you never get an object of the specified class, but always a private subclass. Instead of a `NSArray` you will always get a `NSCFArray`, which is a subclass of `NSArray` that is also a till-free bridge to the `CFArrayRef` type from Core Foundation _(A low level framework underneath Cocoa that is not Objective-C)_.
PeyloW
+2  A: 

NSСFArray is subclass of NSMutable Array

You can use isKindOfClass to check it

if ([myAction isMemberOfClass:[Look class]]) {
    currentActionArray = [self createLookArray:(Look *)myAction item:myItem];
} else if ([myAction isMemberOfClass:[Use class]]) {
        currentActionArray = [self createUseArray:(Use *)myAction item:myItem];
} else if ([myAction isMemberOfClass:[Exit class]]) {
        currentActionArray = [self createExitArray:(Exit *)myAction item:myItem];
} else if ([myAction isKindOfClass:[NSArray class]] ) {
        NSLog(@"--- CUSTOM ACTION --- %@", myAction);
        currentActionArray = (NSArray *)myAction;
}
oxigen
+3  A: 

Two possibilities worth considering:

mouviciel