NSInvocation invocationWithMethodSignature, аргумент подписи метода не может быть ноль
Я следовал инструкциям с официального сайта cocos2d. Я пытаюсь создать несколько пунктов для меню, при создании я передаю селектор с одним параметром. Для каждого предмета я передаю разные селекторы. Я думаю, что здесь проблема, но я действительно не понимаю, почему здесь проблема. Мой заголовочный файл выглядит так:
// 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
Файл реализации:
// 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
1 ответ
Вы получили одинаковую опечатку во всех трех вызовах создания пункта меню. Вы говорите пунктам меню, что селектор, который они должны использовать, называется doSomenthing...
(обратите внимание на ложный n в середине):
CCMenuItemImage *menuItem1 = [... selector:@selector(doSomenthingOne:)];
CCMenuItemImage *menuItem2 = [... selector:@selector(doSomenthingTwo:)];
CCMenuItemImage *menuItem3 = [... selector:@selector(doSomenthingThree:)];
но настоящие имена ваших методов doSomethingOne:
, doSomethingTwo:
, а также doSomethingThree:
,
Точная причина сообщения об ошибке заключается в том, что позже, когда пункт меню должен выполнить этот селектор, он попросит ваш класс сообщить ему сигнатуру метода для селектора, который вы ему дали. Так как вы дали элементу неправильный селектор, ваш класс не знает сигнатуру и возвращает nil
, Пункт меню пытается построить NSInvocation
объект в любом случае, чтобы выполнить свое действие, которое терпит неудачу, потому что вызов не может быть создан с nil
подпись.
Исправьте опечатки, и все должно работать нормально.