Селекторы в методе расписания Cocos2d - PullRequest
2 голосов
/ 19 июня 2011

Итак, я делаю это для инициализации моего селектора:

//In .h

SEL selectors[3];

//In .m

selectors[0] = @selector(rotate);
selectors[1] = @selector(discharge);

И вот проблема:

Когда я вызываю это в моем методе инициализации в Cocos2d следующим образом:

[self performSelector:selectors[0]];

работает нормально, но когда я вызываю эту строку кода в методе с именем moveThings, который вызывается по расписанию ([self schedule:@selector(moveThings:)]) в конце моего метода init в Cocos2d, он выдает EXC_BAD_ACCESS.В чем проблема с расписанием?

ОБНОВЛЕНИЕ:

Я обнаружил, что есть проблема с функцией поворота (функция хранится в селекторе [0]).Вот оно:

-(void)rotate:(ccTime)delta {
    if (((CCSprite *)[creature objectAtIndex:0]).rotation < 360) {
        ((CCSprite *)[creature objectAtIndex:0]).rotation++;
    }
    else {
        ((CCSprite *)[creature objectAtIndex:0]).rotation++;
    }
}

Если я закомментирую содержимое метода, он будет работать нормально при вызове через moveThings и init.

Если я изменю содержимое метода с помощью:

((CCSprite *)[creature objectAtIndex:0]).rotation++;

Не получается ... Но, опять же, я хотел бы заявить, что все эти вещи работают, если я вызываю его в своем методе init, даже вызываю его дважды подряд, но он не будет работать (кромекогда я вынимаю содержимое метода rotate), если я вызываю его с помощью метода moveThings:, который вызывается с помощью метода schedule, он не работает.

Дальнейшее обновление:

Если я вызываю:

((CCSprite *)[creature objectAtIndex:0]).rotation++;

В moveThings (который, как я уже говорил, вызывается методом schedule:(SEL)) он не работает.Там, где он не вызывается через метод, вызываемый по расписанию, он работает.

Ответы [ 4 ]

6 голосов
/ 24 июня 2011

Проблема в том, что при вызове executeSelector есть только две опции:

  1. пусть ваш селектор не принимает аргументов и оставляет ":" вне определения @selector (foo).
  2. пусть ваш селектор принимает один или два аргумента , которые оба должны быть NSObject или подклассом

Я подозреваю, что это последнее, что запутывает вас здесь.

Вот три формы performSelector:

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

Вы заметите, что все аргументы withObject имеют тип id, который является объектом Objective C.

Селектор, который вы пытаетесь использовать, получает ccTime, который является float и , а не объектом Objective C, поскольку он является параметром, и именно поэтому вещи терпят крах:

-(void)rotate:(ccTime)delta;

Одним из вариантов является создание метода-обертки, который принимает обернутый ccTime, разворачивает его и вызывает метод rotate:(ccTime):

- (void) wrappedRotate: (NSNumber*) inDelta
{
    [self rotate: [inDelta floatValue]];
}

затем используйте

selectors[0] = @selector(wrappedRotate:);

, а затем позвоните через:

[self schedule: @selector(moveThings:)]);  // cocos2d schedule

... 

- (void) moveThings: (ccTime) dt
{
   [self performSelector: selectors[0] withObject: [NSNumber numberWithFloat: dt]];
  ...
}

Одна из причин, по которой вы путаетесь, заключается в том, что Cocos2d использует @selector несколько более сложными способами (см. CCScheduler.m в CCTimer :: initWithTarget: selector: interval: и CCTimer :: update: метод в частности).

отказ от ответственности: код, введенный в SO, поэтому не проверяется компилятором, но суть того, что вам нужно, должна быть здесь.

0 голосов
/ 19 июня 2011

Я думаю, что ваша проблема проистекает из определения вашего метода, которое - (void)rotate;, а не - (void)rotate:(ccTime)dt;

Вы также должны настроить селекторы.

0 голосов
/ 20 июня 2011

Если у вашего метода нет аргументов, не используйте двоеточие в вызове селектора.

// Requires @selector(foo:)
- (void) foo:(id)sender;
// Requires @selector(foo)
- (void) foo;
0 голосов
/ 19 июня 2011

Одна проблема наверняка заключается в том, что вы используете переменную, объявленную внутри .h, при инициализации ее внутри относительного .m. По ссылке я не уверен, что будет существовать только одна переменная selectors (поэтому разные файлы, включающие .h, будут иметь разные версии).

Прежде всего, я предлагаю вам попробовать добавить ключевое слово extern, чтобы иметь

extern SEL selectors[3];

, чтобы сообщить вашему компоновщику, что он инициализирован внутри относительного .m, и использовать только этот.

...