user704010
user704010

Reputation:

NSInvocation invocationWithMethodSignature, method signature argument cannot be nil

I followed tutorial from cocos2d official site . I try to create some items for a menu when creating them i pass a selector with one parameter. For each item i pass different selector . I think here is the problem , but i dont see realy why here is the problem. My header file looks :

// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "CCTouchDispatcher.h"

// HelloWorldLayer
@interface HelloWorldLayer : CCLayer {

    CCSprite *first;
    CCSprite *second;
}

// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;
- (void) setUpMenus;
- (void) doSomethingOne: (CCMenuItem  *) menuItem;
- (void) doSomethingTwo: (CCMenuItem  *) menuItem;
- (void) doSomethingThree: (CCMenuItem  *) menuItem;

@end

Implementation file :

// Import the interfaces
#import "HelloWorldLayer.h"

// HelloWorldLayer implementation
@implementation HelloWorldLayer

+(CCScene *) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    HelloWorldLayer *layer = [HelloWorldLayer node];

    // add layer as a child to scene
    [scene addChild: layer];

    // return the scene
    return scene;
}

- (void) doSomethingOne: (CCMenuItem  *) menuItem 
{
    NSLog(@"The first menu was called");
}
- (void) doSomethingTwo: (CCMenuItem  *) menuItem 
{
    NSLog(@"The second menu was called");
}
- (void) doSomethingThree: (CCMenuItem  *) menuItem 
{
    NSLog(@"The third menu was called");
}


// on "init" you need to initialize your instance
-(id) init
{
    // always call "super" init
    // Apple recommends to re-assign "self" with the "super" return value
    if( (self=[super init])) {

        first = [CCSprite spriteWithFile:@"seeker.png"];
        first.position = ccp(100, 100);

        [self addChild:first];

        second = [CCSprite spriteWithFile:@"Icon.png"];
        second.position = ccp(50, 50);

        [self addChild:second];

        [self schedule:@selector(nextFrame:)];

        [self setUpMenus];

        self.isTouchEnabled = YES;
    }

    return self;
}


- (void) registerWithTouchDispatcher {

    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}

- (BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {

    return YES;
}

- (void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {

    CGPoint location = [self convertTouchToNodeSpace: touch];

    [second stopAllActions];

    [second runAction: [CCMoveTo actionWithDuration:1 position:location]];

}

- (void) nextFrame:(ccTime)dt {

    first.position = ccp( first.position.x + 100*dt, first.position.y );

    if (first.position.x > 480+32) {

        first.position = ccp( -32, first.position.y );
    }
}

- (void) setUpMenus {

    CCMenuItemImage *menuItem1 = [CCMenuItemImage itemFromNormalImage:@"myfirstbutton.png" 
                                                        selectedImage:@"myfirstbutton_selected.png" 
                                                               target:self 
                                                             selector:@selector(doSomenthingOne:)];

    CCMenuItemImage *menuItem2 = [CCMenuItemImage itemFromNormalImage:@"mysecondbutton.png" 
                                                        selectedImage:@"mysecondbutton_selected.png" 
                                                               target:self
                                                             selector:@selector(doSomenthingTwo:)];
    CCMenuItemImage *menuItem3 = [CCMenuItemImage itemFromNormalImage:@"mythirdbutton.png" 
                                                        selectedImage:@"mythirdbutton_selected.png" 
                                                               target:self selector:@selector(doSomenthingThree:)];

    CCMenu *myMenu = [CCMenu menuWithItems:menuItem1,menuItem2,menuItem3, nil];

    [myMenu alignItemsVertically];

    [self addChild:myMenu];

}



// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
    // in case you have something to dealloc, do it in this method
    // in this particular example nothing needs to be released.
    // cocos2d will automatically release all the children (Label)

    // don't forget to call "super dealloc"
    [super dealloc];
}
@end

Upvotes: 2

Views: 2861

Answers (1)

jscs
jscs

Reputation: 64002

You've got the same typo in all three menu item creation calls. You're telling the menu items that the selector they should use is called doSomenthing... (note the spurious n in the middle):

CCMenuItemImage *menuItem1 = [...  selector:@selector(doSomenthingOne:)];
CCMenuItemImage *menuItem2 = [...  selector:@selector(doSomenthingTwo:)];
CCMenuItemImage *menuItem3 = [...  selector:@selector(doSomenthingThree:)];

but the actual names of your methods are doSomethingOne:, doSomethingTwo:, and doSomethingThree:.

The exact cause of the error message is that later, when the menu item needs to perform that selector, it will ask your class to tell it the method signature for the selector you gave it. Since you gave the item an incorrect selector, your class doesn't know the signature, and it returns nil. The menu item tries to construct an NSInvocation object anyways to perform its action, which fails because the invocation can't be created with a nil signature.

Fix the typos and everything should work fine.

Upvotes: 1

Related Questions