1

Possible Duplicate:
'isMemberOfClass' returning 'NO' when custom init

I've some trouble with the "isMemberOfClass"-Method.

I have a class, that generates and returns objects ("MyObject")

// ObjectFactory.h
...
-(MyObject*)generateMyObject;
...

// ObjectFactory.m
...
-(MyObject*)generateMyObject
{
    MyObject *obj = [[MyObject alloc]init];
    obj.name = @"Whatever";      // set properties of object
    return obj;
}
...

And there's a unittest-class, that calls the generateMyObject-selector and checks the class of the returned object:

...
ObjectFactory *factory = [[ObjectFactory alloc]init];
MyObject *obj = [factory generateMyObject];
if (![obj isMemeberOfclass:[MyObject class]])
    STFail(@"Upps, object of wrong class returned...");
else
...

I expect, that the else-part is processed...but the STFail(...) is called instead, but why?

Thx for any help! Regards, matrau

Ok, here is the original copy&pasted code:

//testcase
- (void)test001_setCostumeFirstCostume
{
    NSString *xmlString = @"<Bricks.SetCostumeBrick><costumeData reference=\"../../../../../costumeDataList/Common.CostumeData\"/><sprite reference=\"../../../../..\"/></Bricks.SetCostumeBrick>";
    NSError *error;
    NSData *xmlData = [xmlString dataUsingEncoding:NSASCIIStringEncoding];
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData
                                                           options:0 error:&error];
    SetCostumeBrick *newBrick = [self.parser loadSetCostumeBrick:doc.rootElement];
    if (![newBrick isMemberOfClass:[SetCostumeBrick class]])
        STFail(@"Wrong class-member");
}

// "MyObject"
@implementation SetCostumeBrick
@synthesize indexOfCostumeInArray = _indexOfCostumeInArray;

- (void)performOnSprite:(Sprite *)sprite fromScript:(Script*)script
{
    NSLog(@"Performing: %@", self.description);

    [sprite performSelectorOnMainThread:@selector(changeCostume:) withObject:self.indexOfCostumeInArray waitUntilDone:true];
}

- (NSString*)description
{
    return [NSString stringWithFormat:@"SetCostumeBrick (CostumeIndex: %d)", self.indexOfCostumeInArray.intValue];
}

@end

// superclass of SetCostumeBrick
@implementation Brick
- (NSString*)description
{
    return @"Brick (NO SPECIFIC DESCRIPTION GIVEN! OVERRIDE THE DESCRIPTION METHOD!";
}

//abstract method (!!!)
- (void)performOnSprite:(Sprite *)sprite fromScript:(Script*)script
{
    @throw [NSException exceptionWithName:NSInternalInconsistencyException
                                   reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
                                 userInfo:nil];
}
@end

// the "factory" (a xml-parser)
- (SetCostumeBrick*)loadSetCostumeBrick:(GDataXMLElement*)gDataSetCostumeBrick
{
    SetCostumeBrick *ret = [[SetCostumeBrick alloc] init];

    NSArray *references = [gDataSetCostumeBrick elementsForName:@"costumeData"];
    GDataXMLNode *temp = [(GDataXMLElement*)[references objectAtIndex:0]attributeForName:@"reference"];
    NSString *referencePath = temp.stringValue;

    if ([referencePath length] > 2)
    {
        if([referencePath hasSuffix:@"]"]) //index found
        {
            NSString *indexString = [referencePath substringWithRange:NSMakeRange([referencePath length]-2, 1)];
            ret.indexOfCostumeInArray = [NSNumber numberWithInt:indexString.intValue-1];
        }
        else 
        {
            ret.indexOfCostumeInArray = [NSNumber numberWithInt:0];
        }
    }
    else 
    {
        ret.indexOfCostumeInArray = nil;
        @throw [NSException exceptionWithName:NSInternalInconsistencyException
                                       reason:[NSString stringWithFormat:@"Parser error! (#1)"]
                                     userInfo:nil];
    }

    NSLog(@"Index: %@, Reference: %@", ret.indexOfCostumeInArray, [references objectAtIndex:0]);

    return ret;
}

SOLUTION:

Eiko/jrturton gave me a link to the solution - thx: isMemberOfClass returns no when ViewController is instantiated from UIStoryboard

The problem was, that the classes were included in both targets (app and test bundle)

Thank you guys for your help :)

Community
  • 1
  • 1
matrau
  • 148
  • 1
  • 9

2 Answers2

2

You generally want isKindOfClass:, not isMemberOfClass. The isKindOfClass: will return YES if the receiver is a member of a subclass of the class in question, whereas isMemberOfClass: will return NO in the same case.

if ([obj isKindOfClass:[MyObject class]])

For example,

NSArray *array = [NSArray array];

Here [array isMemberOfClass:[NSArray class]] will return NO but [array isKindOfClass:[NSArray class]] will return YES.

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139
  • 2
    That's wrong. isKindOfClass tests with subclasses as well, and here clearly isMemberOfClass should work as well. – Eiko Oct 03 '12 at 15:53
  • That's true but I thought the sub-classing might be the issue. Added details. – Paresh Masani Oct 03 '12 at 16:05
  • `init` methods need not return `self`, they can return some other object, e.g. an instance of a subclass. We don't know if that is the case here, but if it is, applefreak has given the right answer. – Martin R Oct 03 '12 at 16:21
  • @Eiko In the case of `NSArray` the method `isMemberOfClass` returns NO because of the class cluster. For me, `NSLog(@"%@", [array class])` returns `__NSArrayI` which is not `NSArray`. Therefore, `isMemberOfClass` returns NO, whereas `isKindOfClass` returns YES. I think this is a distraction from the OPs question though as their MyObject class is unlikely to be a class cluster so `isMemberOfClass` should work. – mttrb Oct 03 '12 at 16:21
  • @mttrb I know all the details, and for this specific question the answer just doesn't make sense. It's perfectly fine to suggest isKindOfClass: as a comment, but as it cannot solve the problem, it is no answer. – Eiko Oct 03 '12 at 16:27
  • @Eiko I misunderstood your original comment. I read "and here clearly iMemberOfClass should work" as referring to this answer not to the OP's original question. – mttrb Oct 04 '12 at 01:55
0

Ok, with different class addresses per your comment, I think I can track this down to be a duplicate of this:

isMemberOfClass returns no when ViewController is instantiated from UIStoryboard

Basically, your class is included twice.

Community
  • 1
  • 1
Eiko
  • 25,601
  • 15
  • 56
  • 71
  • 1
    This should be a close as duplicate vote, not an answer. – jrturton Oct 03 '12 at 19:03
  • @jrurton I thought so as well at first, but then, there is more "debugging information" in this post than in the other - hence I think this question should receive a proper answer (which obviously links back to the longer original answer). – Eiko Oct 03 '12 at 19:06