开发者

Selectors in Cocos2d schedule method

So I am doing this to initialize my selector:

//In .h

SEL selectors[3];

//In .m

selectors[0开发者_运维知识库] = @selector(rotate);
selectors[1] = @selector(discharge);

And here is the problem:

When I call this in my init method in Cocos2d like this:

[self performSelector:selectors[0]];

it works fine, but when I call this line of code in a method called moveThings which is invoked through the schedule ([self schedule:@selector(moveThings:)]) at the end of my init method in Cocos2d it gives EXC_BAD_ACCESS. What is the problem with scheduling things?

UPDATE:

I have found there is a problem with the rotate function (the function being stored in selector[0]). Here it is:

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

If I comment the contents of the method out it works fine when called through moveThings and init.

If I change the methods contents with:

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

It fails... But, again, I would like to state that all of these things do work if I call it in my init method, even call it twice in a row, but it will not work (except when I take out the contents of the rotate method) if I call it through the moveThings: method which is being invoke through the schedule method it fails.

Further update:

If I call:

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

In moveThings (which is being, as I've said before, invoked by the schedule:(SEL) method) it fails. Where as long as it is not invoked through a method that is the called by schedule it works.


The problem is that when you call performSelector there are only two options:

  1. have your selector take no arguments and leave the ":" off the @selector(foo) definition.
  2. have your selector take either one or two arguments which both must be an NSObject or subclass

it is the latter that is messing you up here I suspect.

Here are the three forms of performSelector:

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

You'll note that the withObject arguments are all of type id which is an Objective C object.

The selector you're trying to use takes a ccTime which is a float and not an Objective C object as it's param and that is why things are crashing:

-(void)rotate:(ccTime)delta;

One option is to make a wrapper method that takes a wrapped ccTime and unwraps it and calls the rotate:(ccTime) method:

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

then use

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

and then call via:

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

... 

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

One reason you are getting confused is because Cocos2d is using @selector in somewhat more complicated ways (see CCScheduler.m in the CCTimer::initWithTarget:selector:interval: and CCTimer::update: method in particular).

disclaimer: code typed into SO so not checked with a compiler, but the essence of what you need should be here.


One problem for sure is that you are using a variable declared inside a .h while initializing it inside the relative .m. According to the linking I'm not sure that just one variable selectors will exist (so that different files that include .h will have different versions).

First of all I suggest you to try adding the keyword extern to have

extern SEL selectors[3];

to tell your linker that it is initialized inside the relative .m and to use just that one.


I think your problem stems from your method definition which is - (void)rotate; and not - (void)rotate:(ccTime)dt;

You should adjust your selectors likewise.


If your method does not have any arguments then do not use a colon in your selector call.

// Requires @selector(foo:)
- (void) foo:(id)sender;
// Requires @selector(foo)
- (void) foo;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜