EXC_BAD_ACCESS when switching CCAnimations - objective-c

I'm new to using CCAnimations in cocos2D, and I've run into a problem that I've had a hard time solving.
I'm making a basic platforming game, and the player sprite has various animations that need to be run depending on the state of the player.
I have the following code in my layer's init method:
sprite = [CCSprite spriteWithSpriteFrameName:#"stand.png"];
standingSprites = [NSArray arrayWithObjects:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"stand.png"],
nil];
runningSprites = [NSArray arrayWithObjects:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"run1.png"],
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"run2.png"],
nil];
standingAnimation = [CCAnimation animationWithFrames:standingSprites delay:0.2f];
runningAnimation = [CCAnimation animationWithFrames:runningSprites delay:0.2f];
animationAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:standingAnimation]];
[sprite runAction:animationAction];
This works as expected with either of the two animations. However, I want to run standingAnimation when the player is standing still and runningAnimation when the player is running. I attempted to do this as follows:
-(void)walk {
if(!isWalking) {
isWalking = true;
[sprite stopAction:animationAction];
animationAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:runningAnimation]];
[sprite runAction:animationAction];
}
}
The second to the last line crashes the program, causing an EXC_BAD_ACCESS (on referencing 0x0). Stepping through walk in the debugger, it doesn't appear that any of the relevant pointers are null.
From the stack trace:
2012-06-03 10:59:59.907 ThirtyMinutes[9876:6403] *** Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason:
'-[NSCTFontDescriptor frames]: unrecognized selector sent to instance
0x7f808d93e9f0'
0x7f808d93e9f0 is the address of runningAnimation.
What am I doing wrong?
Is there a better way of doing this?
Thanks!

The error message is telling you that, at the moment of the error, 0x7f808d93e9f0 is the address of a NSCTFontDescriptor object. The likely reason is that you're not retaining runningAnimation and its memory has been reclaimed for a different object.
(Show the declaration of runningAnimation if its not obvious how that's happening.)

You have to recreate actions every time you want to use them. In your case, you tried to use action after it has been deallocated.

Related

NSArray possibly causing app crash?

I have a method that chooses a random sprite node from an array to place on the screen. My app is crashing though. This is a snippet from the error message:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString decodeObjectForKey:]: unrecognized selector sent to instance 0x47b4'
This is the method I have written out.
-(SKSpriteNode *) gamePieces {
NSArray *things = [NSArray arrayWithObjects: #"piece1", #"piece2", #"piece3", nil];
int r = arc4random () % [things count];
SKSpriteNode *randomObject = [[SKSpriteNode alloc] initWithCoder:[things objectAtIndex:r]];
return randomObject;
}
Any ideas as to what the problem is?
As already mentioned by #HotLicks and #LearnCocos2d, -initWithCoder: is out of place here. Creating a new SKSpriteNode from scratch is typically done with one of the designated initializers (+spriteNodeWithColor:size:,+spriteNodeWithImageNamed: or spriteNodeWithTexture:). Assuming you just wish to create an SKSpriteNode with a random image, take a look at the following code.
- (SKSpriteNode *) randomGamePiece {
NSArray *filename = [NSArray arrayWithObjects: #"piece1", #"piece2", #"piece3", nil];
int r = arc4random () % [things count];
NSString * randomFilename = [things objectAtIndex:r];
SKSpriteNode *randomObject = [SKSpriteNode spriteWithImageNamed:randomFilename];
return randomObject;
}
I wholeheartedly recommend browsing through the Sprite Kit Programming Guide which contains many useful snippets and pointers for new and intermediate Sprite Kit programmers.

NSImageView - Huge memory leak?

For some reason, the allocation of two NSImageViews creates a huge memory leak.
Although dealloc method gets called in both NSImageViews.
I'm using ARC.
With NSImageViews
As soon as the following getter method is called, a lot of memory is used.
This would be ok, but it doesn't get deallocated when the window is being closed...
- (NSView *)animationView {
if (!_animationView) {
_animationView = [[NSView alloc] initWithFrame:self.bounds];
self.oldCachedImageView = [[NSImageView alloc] initWithFrame:self.bounds];
[_animationView addSubview:self.oldCachedImageView];
self.oldCachedImageView.wantsLayer = YES;
self.cachedImageView = [[NSImageView alloc] initWithFrame:self.bounds];
[_animationView addSubview:self.cachedImageView];
self.cachedImageView.wantsLayer = YES;
self.animationView.wantsLayer = YES;
}
return _animationView;
}
The first circle is when the getter method above is called.
The second is when the window is deallocated.
Without NSImageViews
Not with the two NSImageViews commented out.
- (NSView *)animationView {
if (!_animationView) {
_animationView = [[NSView alloc] initWithFrame:self.bounds];
/*
self.oldCachedImageView = [[NSImageView alloc] initWithFrame:self.bounds];
[_animationView addSubview:self.oldCachedImageView];
self.oldCachedImageView.wantsLayer = YES;
self.cachedImageView = [[NSImageView alloc] initWithFrame:self.bounds];
[_animationView addSubview:self.cachedImageView];
self.cachedImageView.wantsLayer = YES;
self.animationView.wantsLayer = YES;
*/
}
return _animationView;
}
No memory leak here...
Anyone an idea why this happens?
Use Instruments to trace the "Leaks". There is a Leaks tool in Instruments. Run it through the use of your app, all the way until you close your it completely. Make sure ARC isn't just deallocating it at a later time, which is possible. Keeping it in memory for a while allows for a faster retrieval if needed again.
However, if you do see a leak displayed, then there is an issue. Make sure there are no references to it you aren't noticing.
Use the leaks tool to figure out the memory location that is leaking if it displays some. Then try to match it with some object in your code. In other words, make sure it is the NSImageView that is leaking.
You can use:
NSLog(#"Location = %#",NSObjectHere);
To get the memory location. If it matches, then go back, once more, and find the reference you have to it. Unless it's an ARC bug, which is possible, though unlikely, then you are holding a reference to it somewhere.
For any more detail, please update your question with more code, no one can debug it for you without seeing more code.
Good luck!
EDIT
Tutorial explaining the use of the Leaks tool at http://mobileorchard.com/find-iphone-memory-leaks-a-leaks-tool-tutorial/

Making the bullet Fire -Cocos2d

My code has two Bullet-related classes. Bullet and BulletCache. The BulletCache creates a certain number of
I have moved on to just creating a new bullet creating method meant to shoot off the bullets. I used the CCFuncN method but the game is currently throwing NSException errors:
CCAction* action = [CCSequence actions:
[CCAnimate actionWithAnimation:[profile getAnimation:#"attack" index:currentDir]],
[CCCallFuncN actionWithTarget:self selector:#selector(shootBulletFrom:)],
nil];
NSInvalidArgumentException', reason: '-[Player shootBulletFrom:]: unrecognized selector sent to instance 0x703ec70'
edit:
For further help and advice here is the shootBulletFrom method in the BulletCache.
This method is in the BulletCache
-(void) shootBulletFrom:(CGPoint)startPosition velocity:(CGPoint)velocity frameName:(NSString*)frameName
isPlayerBullet:(bool)isPlayerBullet
{
CCArray* bullets = [batch children];
CCNode* node = [bullets objectAtIndex:nextInactiveBullet];
NSAssert([node isKindOfClass:[Bullet class]], #"not a Bullet!");
Bullet* bullet = (Bullet*)node;
[bullet shootBulletAt:startPosition velocity:velocity frameName:frameName
isPlayerBullet:isPlayerBullet];
nextInactiveBullet++;
if (nextInactiveBullet >= [bullets count])
{
nextInactiveBullet = 0;
}
}
I was also recommended to change the [CCCallFuncN] call at the bottom to:
[CCCallFuncN actionWithTarget:self selector:#selector(shootBulletFrom:shotPos velocity:velocity frameName:#"bullet1big.png" isPlayerBullet: YES)],
But then I got the compile Error: Expected ':' before Velocity
You have not mentioned the code for shootBulletFrom, and the error denoted that there is some mistake in the same. May be you have not declared the function in .h file or some other. So if possible mention so.
You can go through this and this links. They are having good examples for bullet firing apps. Hope that helps you.

Deallocated instance exception with threads

I've a problem with an app for Mac that I'm writing in Objective-c.
I've this situation:
In main thread (GUI):
ftEngine = [[FileT alloc] init];
[ftEngine setParameters:searchWord selectedEngine:[[pbEngines selectedItem] title] actualPage:0];
NSThread* thFileT = [[NSThread alloc] initWithTarget:ftEngine selector:#selector(setTotalResult) object:nil]; [thFileT start];
In child (ftEngine previous declared):
-(void)setTotalResult {
NSError* nsError = nil;
NSURL* urlCompleteUrl = [NSURL URLWithString:m_completeSearchWord];
}
m_completeSearchWord is initialized by setParameters function previously utilized.
And now.. my problem is:
When thread is started, it call setTotalResult function and i'll get an exception when I try to use m_completeSearchWord.
It's strange becacuse if I don't use a thread, all works correctly!
Exception is:
2011-09-08 23:24:06.731 GUI[12935:1a07] *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x1003cc650
It sounds like you may not have retained m_completeSearchWord correctly when you initialized it. Add the body of -setParameters if you want help confirming that.
When calling selectors in a new thread, make sure that the selector has been properly wrapped with an autorelease pool :
-(void) setTotalResult {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
...
[pool release];
}
I see all manner of memory related issues when I forget to add the pool and your error definitely rings a bell.

Object changes from NSMutableArray to NSData to NSString

I have a program which works normally. Then I downloaded some code from http://github.com/matej/MBProgressHUD to show a progress meter when doing something.
This is the code that makes the progress meter pop up.
[HUD showWhileExecuting:#selector(myTask) onTarget:self withObject:nil animated:YES];
This will show a progress meter while the method myTask is running.
This is the code for the showWhileExecuting method.
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {
methodForExecution = method;
targetForExecution = [target retain];
objectForExecution = [object retain];
// Launch execution in new thread
taskInProgress = YES;
[NSThread detachNewThreadSelector:#selector(launchExecution) toTarget:self withObject:nil];
// Show HUD view
[self show:animated];
}
If I use this to call the function myTask then one of my class properties will change from an NSMutableString to an NSData object somewhere, and then later on it will change to an NSString. I don't see anywhere in the code that causes this to change, so it's probably some kind of bug. Is memory getting corrupted? What's causing this to happen?
Most likely it's a memory (retain/release issue). If you don't properly retain an object, it may get released out from under you. At that point, the memory will be reclaimed by the OS, which may decide to store something else there. Try turning on NSZombies, and double checking your retain/release/autoreleases.