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:
- have your selector take no arguments and leave the ":" off the @selector(foo) definition.
- 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;
精彩评论