Cocos2d: nasty exception with batched sprites - ios

I can't quiet figure how to debug this. I have a CCScene running and when the scene is replaced I get the following error message.
The scene has a sprite batch node where the CCSpriteSubclass is added.
That's the cleanup method and below that you will find the assertion failure message:
-(void) cleanup
{
[[GameController sharedGameController].musicLayer removeMusicSourceForKey:backgroundMusicFileName];
[CCTextureCache purgeSharedTextureCache];
[CCSpriteFrameCache purgeSharedSpriteFrameCache];
[CCAnimationCache purgeSharedAnimationCache];
// [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[super cleanup];
}
The batch node is created as following in the initWithId:(int)sceneId method:
//Prepare sprites sheets for the rest of the game art
[frameCache addSpriteFramesWithFile:[NSString stringWithFormat:#"art%i-hd.plist", sceneId]];
sharedSpriteMainBatchNode = [CCSpriteBatchNode batchNodeWithFile:[NSString stringWithFormat:#"art%i-hd.png", sceneId]];
And then I add all CCSpriteSubclass objects.
That's the assertion failure message:
** Assertion failure in -[CCSpriteSubclass setTexture:], /Users/xxx/Desktop/xxx/xxx/libs/cocos2d/CCSprite.m:934
2012-12-03 12:54:33.335 RockTale[869:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'CCSprite: Batched sprites should use the same texture as the batchnode'
*** First throw call stack:
(0x338d28bf 0x303c61e5 0x338d27b9 0x311193b3 0x9ad43 0x9a2fb 0x4bca3 0x44ddf 0x38b07 0x503f7 0x94c03 0xbbeed 0xbcfe7 0x34fb7423 0x34fb7379 0x31b4cf93 0x36e52891 0x3389bf43 0x338a6553 0x338a64f5 0x338a5343 0x338284dd 0x338283a5 0x37f9afcd 0x3128b743 0x2edf 0x2ea0)
terminate called throwing an exception(lldb)
EDIT: Added a breakpoint to the setTexture method and here is what I "DON't" see :)
EDIT 2: I whish I could manage to retrieve the full stacktrace like in Java.. I have asked this in a different question and I was told I should add a global exception.. I still need to figure out how to retrieve the stacktrace..

From the text of your exception message it seems that you create sprites with spriteframes from different spritesheets.

I solved this problem in the same way as here. It was due to the fact that sprite frames where referred while the previous class was replacing the existing one and hence the previous class cleanup method was calling the purge frame cache which was consequently removing the yet unused sprite frames which where being loaded in memory by the newly created object.

Related

Odd error (UITextSelectionView) while calling a method?

I'm facing a problem while calling a method and I don't know how figure it out.
Basically, during the main menu, I want to call a SKNode showing a tutorial part. The code is the following:
- (void)didMoveToView:(SKView *)view
{
...
if ([[GameData sharedData] openingTutorial]) { // Checks if the menu needs the tutorial
[_tutorialObj performSelector:#selector(runTutorialWithStep:)
withObject:[NSNumber numberWithInt:8]
afterDelay:3.0
];
}
}
When the method didMoveToView: is called (even before waiting the 3 seconds for the runTutorialWithStep:), I got this error:
[UITextSelectionView name]: unrecognized selector sent to instance 0x1576e6c0
2014-10-14 11:01:19.430 [406:130379] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITextSelectionView name]: unrecognized selector sent to instance 0x1576e6c0'
The odd thing is that in the previous class I use the same tutorial's action in the didMoveToView: and it's working right. But...
Thing is getting more strange here!!!
If I use an intermediary method for this calls:
- (void)didMoveToView:(SKView *)view
{
...
[self performSelector:#selector(intermediaryMethod)
withObject:nil
afterDelay:3.0
];
}
- (void)intermediaryMethod
{
[_tutorialObj performSelector:#selector(runTutorialWithStep:)
withObject:[NSNumber numberWithInt:8]
afterDelay:0.0
];
}
Everything works without issues. I don't want to avoid the problem but solve this. Any advices?
The error says it all. You try to send a 'name' message to object that doesn't implement it (UITextSelectionView). Since your second take works the cause is either in
[[GameData sharedData] openingTutorial]
method or before this call. Search for objects calling 'name' and check if it's the UITextSelectionView in question.
That or maybe you have weak reference to general view object and during those three seconds before calling runTutorialWithStep you reassign it to object that implements 'name' message.
Ok, I solved the problem.
I added a breakpoint for every exception and I realized that the issues was due to an other class (the only one with UITextView).
Basically I removed the text field from its parent ([self removeFromParent]) by my own once I did not need it anymore.
I suppose the error was fired during the deallocation 'cause the program can't find the UITextView. I managed to remove this statement and everything works right.
Actually I still have doubts because I don't understand why this exception is throw only if I call the [_tutorialObj runTutorialWithStep:] method.
I found the way to fix it.
UITextView *textView = .....
textView.selectable = NO;

app crashing due to resource not loading properly randomly

basically Im making a game on Sprite Kit using Obj-C in XCode 5
whenever I tap the screen, I use an SKAction to play a sound file
[self runAction:[SKAction playSoundFileNamed:#"tap.caf" waitForCompletion:NO]];
Previously I used the mp3 file that i had of the same sound and the error kept popping up randomly after about more than 50 taps at least, sometimes more sometimes less, sometimes it doesn't even cause an error,
So i read the apple documentation and decided to convert to ima4 .caf extention.
I'm not sure if its made a difference, It happens much less often. I've got 2 more audio files that are played through SKActions and none of them have yet failed loading.
Any suggestions?
Debug console output below:
2014-07-05 16:14:15.716 GoUp[777:60b] *** Terminating app due to uncaught exception
'Failed to Load Resource', reason: 'Resource tap.caf can not be loaded'
*** First throw call stack:
(0x306d7fd3 0x3ae86ccf 0x306d7f15 0x32e09e55 0x32dc2b2d 0xf9331 0x32de69ab 0x32f28651
0x32f236eb 0x32ef88ed 0x32ef6f97 0x306a325b 0x306a272b 0x306a0f1f 0x3060bf0f 0x3060bcf3
0x35510663 0x32f5716d 0xfcd61 0x3b393ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Just to add, I tried to check if the file was faulty by setting a repeatforever waitforcomplete:YES SKAction playing the sound file, (i did wait for it to complete each time otherwise, it may have crashed due to significant number of actions). It ran without problem for at least 5 mins, until i decided to stop the app. Not sure if this confirms the file is not damaged
EDIT 2 : Just tried a different sound file and it happened again with a different file :(
I have no explanation about why that "crash" occurs,
but, you can easily solve this problem by declaring and loading your sounds into cash (to avoid to load it each time the sound is played) as follow:
In the .h
#property (strong, nonatomic) SKAction *aSound;
in the .m
Ignit it on the top:
self.aSound = [SKAction playSoundFileNamed:#"FileName.wav" waitForCompletion:NO];
En then call it each time you want to play the sound:
[self runAction:_aSound];
Also and for some reasons,
I advice you to convert all your Audios files into .Wav, which is uncompressed (allowing much more speed from the Processor that hasn't uncompressed the file before to read it)
It also dodge a lot of exceptions in C picked-up from the Breakpoint of Xcode.

Unity iOS game crashing with NSInternalInconsistencyException

I am using Prime31's GameCenter Turn Based plugin in my game in order to handle online matches. A problem arises when I receive an "invitation to play" notification from Game Center while Game Center's matchmaker is showing (called using the plug-in => GameCenterTurnBasedBinding.findMatch(2,2,false); ).
The app crashes and the following output is shown in Xcode:
2012-08-20 08:39:27.050 Cabrais[1808:707] *** Assertion failure in -[NSIndexPath row], /SourceCache/UIKit/UIKit-1914.85/UITableViewSupport.m:2606
2012-08-20 08:39:27.052 Cabrais[1808:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
*** First throw call stack:
(0x355ec88f 0x33210259 0x355ec789 0x349e03a3 0x32d4d673 0x35dba49d 0x35dd90e5 0x35dd9379 0x32d4cefb 0x32d4bfd9 0x32d4b763 0x35da7657 0x32ceff37 0x3554b1fb 0x32716aa5 0x327166bd 0x327165c9 0x35dd8179 0x35da936b 0x35dbce65 0x35dbb6b3 0x33979c59 0x33984e91 0x355bf2ad 0x355424a5 0x3554236d 0x332dd439 0x32d1acd5 0x6954 0x3388)
terminate called throwing an exception(lldb)
I have tried disabling notifications through the Ipad/Iphone settings for both my app and GameCenter as well as through the code by removing all notification related code but this hasn't had any effect at all.
I know through debugging that the code in my function attached to GameCenterTurnBasedManager.handleTurnEventEvent doesn't get called before the crash occurs, and neither does the one registered to EtceteraManager.remoteNotificationReceived. (Both these function work perfectly fine otherwise.)
I have asked Prime31 and they have told me that the exception is a mishandling of the tables data source, and to file a bug report with Apple.
Has anyone experienced a similar crash/error while working with Unity?
And is there any way I can try to catch the notification before it arrives and remove the matchmaker or be able to handle the error from unity?
Any insight/help/comments would be greatly appreciated,
Thanks.

cocos2d - NSMutableArray with levels, restart level and crash, next level works good

I've nsmutablearray with levels and two buttons. Next level and try again. When user touched next level, I set objectAtIndex:indexCurrLevel+1 and next level is loading without problem. But if user touched try again and I try to set level to objectAtIndex:indexCurrLevel app crashed with children already added error.
That is crazy because if I set manually try again for ex. objectAtIndex:5 works perfectly until user don't playing on 5 level, because app crashed.
For index different than current level index, works perfectly. (objectAtIndex:index - works)
manually set index gave the same reason as with index.
[self removeFromParentAndCleanup:YES];
Levels *l = [levels2 objectAtIndex:index-1];
Game *hl = [[Game alloc]initWithObstacles:[l staticO] :[l rotateO]:[l lvl]:[l level]:[l pendulumO]:self.levelsArray];
[hl setLevels2:self.levels2];
[hl setBasketY:[l basketY]];
[hl setBasketX:[l basketX]];
[l release];
[[CCDirector sharedDirector] replaceScene:(CCScene*) hl];
[hl configureLevel];
[hl release];
Eroor:
Assertion failure in -[Game addChild:z:tag:],
../libs/cocos2d/CCNode.m:388
2012-05-11 19:03:20.349 Game[932:10a03] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'child already added. It can't be added again'
* First throw call stack:
Guessing an array-bounds issue, but it's impossible to verify without a code sample or crash log.
Try removing the statement [l release]. In general you should only release an object on which you have called retain or else which you have obtained using a method that begins with init, new or copy. The array levels2 will also be retaining each level, and it may be appropriate to leave it as the levels' owner. Run the static analyser in Xcode to pick up these issues.
Read the message : you are trying to addChild an object which already has a parent ... ie has already been added as a child of a CCNode descendant somewhere else in your code base. Line 388 of CCNode is an NSAssert, not breakable. Change CCNode temporarily to have a breakable instruction, as follows:
if (nil==child) {
CCLOG(#"%#<addChild> : have nil child. not adding.",self.class);
return;
}
if (child.parent) {
CCLOG(#"%#<addChild> : This child is already added somewhere. not adding.",self.class); // **** PUT BREAKPOINT HERE *****//
return;
}
NSAssert( child != nil, #"Argument must be non-nil"); // was line 388
NSAssert( child.parent == nil, #"child already added. It can't be added again");
the last 2 lines are from CCNode (in my project). If the error you mention occurs, i would put a break at the line indicated, rerun, and look at the stack trace. When you are done with your dev/test cycle, and such things matter to you, remember to restore cocos2d to its original state for such temporary mods.

Program crashed in iOS5 and normal in iOS4?

My game created in cocos2d 0.99.5.I tested it and released in App Store already.
After I updated my iPhone from iOS4.3.3 to iOS5.0, my game crashed so frequent.
* Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSArrayM: 0x668a540> was mutated while being enumerated.'
* First throw call stack:
(0x30bed8bf 0x37d921e5 0x30bed3e3 0x5cd1 0x2f837 0xa577b 0xae245 0xcc29d 0xcdfed 0x322ee423 0x322ee379 0x358d3f93 0x31e81891 0x30bb6f43 0x30bc1553 0x30bc14f5 0x30bc0343 0x30b434dd 0x30b433a5 0x33771fed 0x32bb5743 0x2c65 0x2bf8)
terminate called throwing an exception
This crash broken memory stack.After I added "objc_exception_throw" breakpoint. I found crash happening in for{} NSArray loop.
I don't know why this crash only happened is iOS5.This test of game is ready for new version and new content.I can't resolve this problem and feel dejected.
Could someone help me?
====================================
update(11/3/11):
NSMutableArray *monsterArray; // monsters information
[gameObject schedule:#selector(gameSchedule:) interval:1.0/30]; // schedule for everything update
- (void) gameSchedule:(ccTime)_dt
{
...
for ( Monster *mon in monsterArray ) // here causing crash
{
...
// check every monster state
}
}
I don't know thread module of cocos2d thoroughly.In my game project, there are some CCAction do sequence action:
id action = [CCSequence actions:
...,
[CCCallFunc actionWithTarget:self selector:#selector(doSth:)],
nil];
[object runaction:action];
- (void)doSth:(id)_sender
{
//some selector modified object value in monsterArray
//some selector deleted or added object in monsterArray
}
Whether cocos2d creat a new thread for doSth: and causing the crash ?
There are many selector which did these action(modify, delete and add) in my game project.
How can I resolve this problem?
===================================================================
update(11/4/11):
#Amorya
I checked Documents about NSCopying protocol.
[monsterArray copy] return a new NSMutableArray.New object in [monsterArray copy] run actions which like CCMove\CCSequence\CCJump will causing correct process?I don't understand.Please explain it.
#Brad Larson
I added a Symbolic breakpoint "objc_exception_throw" and find out the for{} NSMutableArray loop caused the crash.
Change this line
for ( Monster *mon in monsterArray )
to
for ( Monster *mon in [monsterArray copy] )
You're not allowed to modify an array while iterating over it using fast enumeration (as LearnCocos2D mentioned in a comment). Copying the array is the simplest way to fix that without changing your code's logic.
If you're not using ARC, you'll also need to throw an autorelease in there.

Resources