tags:

views:

399

answers:

2

I have a class that contains a collection of objects. I am trying to create a method that will return the first member of the collection matching a supplied predicate.

Here is the collection method:

...
//predicate is a boolean method that accepts an object as its single parameter
-(id<Notation>) getFirstChildMatching: (SEL) predicate declaredInInstance:(id) instance
{
    NSMethodSignature *sig = [[instance class] instanceMethodSignatureForSelector:predicate];
    NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:sig];
    [myInvocation setTarget:instance];
    [myInvocation setSelector:predicate];

    int numItems = childNotations.count;
    for(int i=0;i< numItems;i++)
    {
     id<Notation> thisNotation = [childNotations objectAtIndex:i];
     [myInvocation setArgument:thisNotation atIndex:2];
     BOOL result =NO;
     [myInvocation retainArguments];
     [myInvocation invoke];
     [myInvocation getReturnValue:&result];

     if (result)
      return thisNotation;

    }

    return nil;
}

I have created a test class that tests this method. Here is the test method plus the predicate:

- (void) testGetFirstChildMatching
{
    Leaf *line1 = [[Leaf alloc] initWithValue:1 step:Step_A andNumber:1];
    Leaf *line2 = [[Leaf alloc] initWithValue:2 step:Step_B andNumber:2];

    SEL mySelector = @selector(valueIs1:);

    id<CompositeNotation> compositeNotation = [[CompositeNotation alloc] init];
    [compositeNotation addNotation:line1];
    [compositeNotation addNotation:line2];

    id notation = [compositeNotation getFirstChildMatching: mySelector declaredInInstance:self];
    STAssertEquals(YES, [notation isKindOfClass:[Leaf class]], @"Should be of type Leaf: %@", notation);
    //Leaf *found = ((Leaf *)notation);
    STAssertEquals([notation value], line1.value, @"Should have found line 1 with value 1: actual %i", [notation value]);
    [line1 release];
    [line2 release];
}

-(BOOL) valueIs1: (Leaf *) leaf
{
    if (leaf.value == 1)
     return YES;

    return NO;
}

What I am finding is that on the "if (leaf.value == 1)" line I am getting an "unrecognized selector sent to class". What doesn't make sense is that the debugger can see the value property and it's value so the object clearly has that select. Any ideas?

btw Leaf implements the notation protocol

+3  A: 

Typo in function definition?

-(BOOL) valueIs1: (Leaf *) Leaf // <== should be "leaf" not "Leaf" ?


The fact that you're getting an "unrecognized selector sent to class", not instance, implies that leaf is a Class. Two things to check:

  • Ensure that Leaf's initializer initWithValue is returning an object.
  • Ensure that addNotation: is correctly adding Leafs to the array.
codelogic
Good argument for choosing a less confusing variable naming strategy.
danielpunkass
actually that was just a typo caused in transposing the code to stackoverflow. They aren't the original names. I'll fix the post
Ian1971
A: 

I eventually found the problem. It was this line

[myInvocation setArgument:thisNotation atIndex:2];

it should have been

[myInvocation setArgument:&thisNotation atIndex:2];

Thanks

Ian1971