'NSInternalInconsistencyException: Do not initialize the TextureCache before the Director' - ios

To find a solution I have gone thru this similar link:
TextureCache Error from Cocos2d when integrated into UIKit App
but seems like it is dealing with this error in a different context..
Question:
I have a UIKit project integrated with Cocos2d. When build, succeeds and runs but, at times crashes after receiving a memory warning with this error:
Assertion failure in -[CCTextureCache init], /Users/MyName/Documents/CSProject/CSProject/libs/cocos2d/CCTextureCache.m:90
Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Do not initialize the TextureCache before the Director’
The cocos2d scene is run from the view controller when a button is touched and the code is given below:
In ViewController.m
-(IBAction)overToCocos:(id)sender{
CCDirector *director = [CCDirector sharedDirector];
CCGLView *glView = [CCGLView viewWithFrame:CGRectMake(-100, -50, 480, 480)
pixelFormat:kEAGLColorFormatRGBA8
depthFormat:0];
glView.opaque = NO;
self.imagePicker.cameraOverlayView.userInteractionEnabled = YES;
[self.imagePicker.cameraOverlayView insertSubview:glView atIndex:0];
[self.imagePicker.cameraOverlayView bringSubviewToFront:glView];
[director setView:glView];
[director runWithScene:[HelloWorldLayer scene]];
}
Since the crash occurs after receiving a memory warning, I tried this
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
if ( [ CCDirector sharedDirector ].view != nil ){
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
}
}
Also added this to AppDelegate's applicationDidReceiveMemoryWarning.
But the crash still exists.. Please point me to the right direction to handle this error..
Thanks in advance!

Related

Cocos2d black screen after app archive

I have cocos2d setup as a sub-project in my iOS app, running the latest release (3.5) and targeting iOS versions 9.0+. The problem I'm having is that the cocos2d screen is black when I download and install the app from TestFairy. I have debugged it both on the simulator and on real device and the cocos2d scene loads properly.
It's a simple finger painting app and it's all based on UIKit. Cocos2d is added to a ViewController in the standard way. The relevant code is:
CCDirector *director = [CCDirector sharedDirector];
// If the director's OpenGL view hasn't been set up yet, then we should create it now. If you would like to prevent this "lazy loading", you should initialize the director and set its view elsewhere in your code.
if ([director isViewLoaded] == NO) {
director.view = [self createDirectorGLView];
[self didInitializeDirector];
}
else {
director.view.frame = [self getCanvasFrame];
[director.view setNeedsLayout];
[director.view layoutIfNeeded];
}
director.delegate = self;
// Add the director as a child view controller.
[self addChildViewController:director];
// Add the director's OpenGL view, and send it to the back of the view hierarchy so we can place UIKit elements on top of it.
[self.targetView addSubview:director.view];
[self.targetView sendSubviewToBack:director.view];
// Ensure we fulfill all of our view controller containment requirements.
[director didMoveToParentViewController:self];
The createDirectorGLView is as follows:
- (CCGLView *)createDirectorGLView {
_glView = [CCGLView viewWithFrame:[self getCanvasFrame]
pixelFormat:kEAGLColorFormatRGB565
depthFormat:0
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
return _glView;
}
I also have a scene which contains the CCNode that handles the drawing. It is created like this:
#implementation IntroScene
- (id)init:(CGRect)frame {
self = [super init];
if (self) {
_canvas = [[LineDrawer alloc] init];
_canvas.contentSize = CGSizeMake(frame.size.width, frame.size.height);
_canvas.position = CGPointZero;
_canvas.anchorPoint = CGPointZero;
[self addChild:_canvas];
}
return self;
}
#end
I can't get access to the console logs for some reason while the app is running from TestFairy so I can't say what's going on there. When I debug from Xcode however, everything looks normal and the cocos2d canvas is loading/working just fine. I have a feeling it might be something to do with the way the project is archiving but I'm not sure. Any ideas?
Edit
So I managed to reproduce it in Debug mode on a device and I saw a few errors which I think are related to TestFairy's screen recording using OpenGL and cocos2d.
2016-06-06 12:49:56.362 GraffiTab[5654:2941813] *** Assertion failure in -[CCRenderStateGL initWithBlendMode:shader:shaderUniforms:copyUniforms:], /Users/georgichristov/Documents/Workspace/Examples/GraffiTab/GraffiTab-iOS/GraffiTab/ExternalLibs/Cocos2d/cocos2d/CCRendererBasicTypes.m:356
2016-06-06 12:49:56.362 GraffiTab[5654:2941813] [visit] error CCRenderState: Blending mode is nil
2016-06-06 12:49:56.705 GraffiTab[5654:2941813] TestFairy: Initializing SDK version 1.7.6 (20160531-772d18b7)
2016-06-06 12:49:58.057 GraffiTab[5654:2941813] TestFairy: Session started successfully
2016-06-06 12:49:58.929 GraffiTab[5654:2941813] Please remove uses of SCRCException!

Can't show the scene second time in Cocos3D

I have a viewController with cocos scene which I push in my navigation controller. In this view controller I have this methods:
-(void) viewDidLoad
{
[super viewDidLoad];
[_cc3FrameView addSubview: [self createGLView]];
CC3Backgrounder.sharedBackgrounder.shouldRunTasksOnRequestingThread = YES;
}
- (void) viewWillAppear:(BOOL)animated
{
if (!sceneInitialized) {
sceneInitialized = YES;
[CCDirector.sharedDirector runWithScene: [[self makePanoramaScene] asCCScene]];
} else {
[CCDirector.sharedDirector resume];
}
[CCDirector.sharedDirector startAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[self runningPanoramaScene] sceneWillShow];
});
}
-(AxPanoramaScene *)runningPanoramaScene
{
CCScene *scene = [CCDirector.sharedDirector runningScene];
AxPanoramaLayer *panoramaLayer = [scene.children lastObject];
AxPanoramaScene *panoramaScene = (AxPanoramaScene *)panoramaLayer.cc3Scene;
return panoramaScene;
}
-(void)viewWillDisappear:(BOOL)animated
{
[CCDirector.sharedDirector pause];
}
While I push this controller - everything is working, but when I pop this controller and push it again - I got the bright pink screen and continuos messages in log:
2014-12-12 19:30:06.447 UniversalMapExample[2262:258353] cocos2d: animation started with frame interval: 60.00
2014-12-12 19:30:06.452 UniversalMapExample[2262:258353] cocos2d: surface size: 768x973
OpenGL error GL_INVALID_OPERATION detected at -[CCES2Renderer resizeFromLayer:] 161
2014-12-12 19:30:06.452 UniversalMapExample[2262:258353] Failed to make complete framebuffer object 0x8219
2014-12-12 19:30:06.453 UniversalMapExample[2262:258353] cocos2d: surface size: 768x973
OpenGL error GL_INVALID_OPERATION detected at -[CCES2Renderer resizeFromLayer:] 161
2014-12-12 19:30:06.453 UniversalMapExample[2262:258353] Failed to make complete framebuffer object 0x8219
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
[***GL ERROR***] GL_INVALID_VALUE: Numeric argument is out of range from glUseProgram(15).
[***GL ERROR***] GL_INVALID_OPERATION: Operation not allowed in current state from glUniform3fv(7, 4, (0.329, 0.944, 0.000)) setting u_cc3LightSpotDirectionModel.
[***GL ERROR***] GL_INVALID_OPERATION: Operation not allowed in current state from glUniformMatrix4fv(12, 1, GL_FALSE,
[0.021050, -0.007339, -0.000000, 0.210503
0.000000, -0.000000, 0.017596, -0.977556
0.005937, 0.017031, 0.000000, -0.660065
0.005926, 0.016997, 0.000000, 1.339256]) setting u_cc3MatrixModelViewProj.
How to correctly push the controller with cocos scene several times? I changed the example from cocos sources to this code. What am I doing wrong here? Please, note - that my controller is not CCDirector - it just contains a view with Cocos scene - the realization is like CC3DemoMultiScene. Thanks!
Remember that the CCDirector is a UIViewController, but it is also a singleton, which give it some unique nuances.
For example, you seem to be invoking the createGLView method every time you want to replace your controller. If it follows the CC3DemoMultiScene design, this will try to recreate another CCGLView before the old one has been released from the CCDirector singleton.
It's generally best to treat the CCDirector and the CCGLView that you create for it as a self-contained reusable unit. As you pop the containing controller, leave everything as is, and simply add and remove the CCGLView from the view hierarchy each time.
...Bill
This is a copy/paste from my blog where I covered a similar issue. The only difference is that I wanted full UIKit integration. I did have the problem where the 2nd time through. Perhaps it will help you.
http://www.notthepainter.com/full-cocos2d-uikit-integration/
I was working on a cocos2d based tapping game and I wasn’t able to run my game twice. It was clear that I wasn’t shutting the 1st game down correctly or building the 2nd game correctly, or both!
There are a lot of tutorials on the web out there teaching you how to add UIKit buttons to your Cocos2D app, or how to launch Cocos2D from your UIKit based app. But I needed to do both. I wanted a UIViewController under my game and UIKit widgets on top of my game. I spent a lot of time reading and this is what I came up with.
First, building the Xcode project was a nightmare. I eventually used the cocos2d/box2d template and then ripped out the files I didn’t needed, and added all my original files back in. The AppDelegate.m file looks just like a non-cocos2d app should look. This goes against the grain of many of the tutorials which advise you to build your cocos2d environment in the AppDelegate. I struggled with that, didn’t have luck for most of a Friday and then on Monday I put in a Cocos2DSingleton and it pretty much ran first time.
Here is my GameViewController’s viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:NO];
TTCocos2DSingleton *shared = [TTCocos2DSingleton sharedCocos2D];
CCGLView *glView = [shared currentGLView];
[self.view insertSubview:glView atIndex:1];
}
There are a view things to note. GameViewController has game UIButtons, score UILabels, and other game type of UI widgets. This lets me do a lot of the game controls in Interface Builder, not laying them out by hand. Notice I hide the status bar since the game is full-screen.
I get my cocos2d instance via the singleton, get its glView and insert this into the GameViewController’s view at index 1. This puts it below all the game controls. I’ll show you the sharedCocos2D method later, lets look at viewWillAppear.
- (void) viewWillAppear:(BOOL)animated
{
if(![[CCDirector sharedDirector] runningScene]){
CCScene *scene = [MyGameLayer scene];
myGame = [MyGameLayer node];
myGame.delegate = self;
[scene addChild: myGame];
[[CCDirector sharedDirector] runWithScene:scene];
} else {
// we have a scene already, replace the original to get a new game
[[CCDirector sharedDirector] startAnimation];
CCScene *scene = [MyGameLayer scene];
myGame = [MyGameLayer node];
myGame.delegate = self;
[scene addChild: myGame];
[[CCDirector sharedDirector] replaceScene:scene];
}
}
Notice how we treat the first run differently from the second run. For the second, and subsequent runs, we replace the scene with a new one. This avoids all “restarting” problems. Also notice that I set a delegate. I use a delegate protocol to communicate between my game layer and my UIViewController.
My singleton pattern comes from the Duck Rowing blog which I must admit is a pretty awesome name for a blog. I’m not going to show all the singleton code here, this blog is about cocos2d, but here is how I build my cocos2d environment.
+ (TTCocos2DSingleton *) sharedCocos2D;
{
static dispatch_once_t onceQueue;
dispatch_once(&onceQueue, ^{
if (sharedInstance) {
return;
}
sharedInstance = [[TTCocos2DSingleton alloc]init];
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
sharedInstance->glView = [CCGLView viewWithFrame:[[UIScreen mainScreen] bounds]
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
[sharedInstance->glView setMultipleTouchEnabled:YES];
[sharedInstance setupDirector];
});
return sharedInstance;
}
The singleton sets up the CCGLView, enables multi-touch and then sets up the director. (I put that in another method since I thought, erroneously, that I’d need to call it elsewhere. Turns out I didn’t need to.)
- (void)setupDirector
{
CCDirectorIOS *director = (CCDirectorIOS*) [CCDirector sharedDirector];
[director setView:glView];
[director enableRetinaDisplay:YES];
director.wantsFullScreenLayout = YES;
[director setDisplayStats:NO];
[director setAnimationInterval:1.0/60];
}
And in setupDirector we set the usual suspects needed for a cocos2d app. Now the game can be played multiple times, I have a full UIViewController/UINavController underneath it, and I have UIKit widgets on top of my game. Nirvana.

unable to find cause of EXC_BAD_ACCESS on a iOS7.1 app

I'm building a small demo app with MQTTKit and Estimote iOS SDK that ranges the beacons and sends the beacons proximity uuid, major and minor to a MQTT broker.
The sample works fine for a while, but sometimes it crashes and I get a EXC_BAD_ACCESS (code=2, address=0x27c8eff4)) on Thread 1 - Queue:com.apple.main-thread. In XCode, while debugging I can see the following when the exception throws:
CoreFoundation`CFRelease:
0x2fdc9f54: push {r4, r5, r6, r7, lr}
That is where the exception occurs, but I have no clue what that represents nor what it means.
Could anyone point out what is that I am not retaining or releasing to early, because from what I have read is something among the lines of objects being released to early and trying to access them after being released?
EDIT: As per the comment's suggestions, I have enabled NSZombies and breakpoints on exceptions and now I get more info:
Pulsr(21312,0x3cb4118c) malloc: *** error for object 0x16f27404: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug
And the line where it stops is at [UIView animateWith ...];:
dispatch_async(dispatch_get_main_queue(), ^(void){
[UIView animateWithDuration:0.250
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
weakSelf.streamingCountLabel.layer.backgroundColor = streaming ? weakSelf.yellowColor.CGColor : weakSelf.redColor.CGColor;
}
completion:nil];
if (!streaming)
{
weakSelf.streamingCountLabel.text = #"0";
}
});
First thing that comes to my mind is this part:
- (instancetype)init
{
self = [super init];
return [self initWithUUID:ESTIMOTE_PROXIMITY_UUID identifier:#"Pulsr"];
}
- (instancetype)initWithUUID:(NSUUID *)uuid identifier:(NSString *)identifier
{
self = [super init];
if (self) {
_manager = [[ESTBeaconManager alloc] init];
_region = [[ESTBeaconRegion alloc] initWithProximityUUID:uuid identifier:identifier];
}
return self;
}
You are calling [super init] two times on one alloc. It might not be a problem but it's definitely wrong approach. In this case just remove [super init] from init method.

How to completely unload SpriteKit Scene

When I hit the retry button in my game, I want it to reload the MainScene. I am doing this with:
-(void)retry
{
SKTransition *transition = [SKTransition fadeWithDuration:.4];
MainScene *gameOver = [[MainScene alloc] initWithSize:self.size];
[gameOver didMoveToView:self.view];
[self.scene.view presentScene:gameOver transition:transition];
}
However, this is causing the memory/CPU usage to increase (by a lot) each time I hit retry. After about 10-20 retries, there is a noticeable lag.
I made all my SKEmitterNode and SKSpriteNode static and that fixed the memory problem, so I suspect that my sprites, emitters, etc are not being released from the memory and are being re-loaded every time I hit retry, doubling it.
I am loading the sprites/emitters like this:
#implementation MainScene {
SKEmitterNode *_bubbleEmitter;
SKSpriteNode *_sunglasses;
...
}
- (id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
_sunglasses = [SKSpriteNode spriteNodeWithImageNamed:#"sunglasses"];
[_sunglasses setPosition:CGPointMake(self.size.width/2, self.size.height + 10)];
[self addChild:_sunglasses];
...
}
return self;
}
Am I loading the sprites or the retry wrong?
This may or may not be the cause, but it's certainly wrong to call this method yourself:
[gameOver didMoveToView:self.view];
The didMoveToView: method is sent to the scene by the SKView when you present the scene. That means this method will actually run twice.
Also verify that your scenes are deallocating properly by implementing:
-(void) dealloc
{
NSLog(#"dealloc: %#", self);
}
Watch for the log or set a breakpoint to confirm the scene deallocates. If it isn't, check for memory leaks and retain cycles.

Getting EXC_BAD_ACCESS when trying to call [UITableView panGestureRecognizer]

Just upgraded xCode to 4.5. iOS 5 is still my deployment target, but Base SDK is now 6.0.
Application now crashes where previously it did not. The project uses ARC.
The offending line is a property call on a UITableView... asking for the panGestureRecognizer (line 3 below).
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIPanGestureRecognizer* pgr = [imageTableView panGestureRecognizer];
[pgr setMinimumNumberOfTouches:2];
[pgr setMaximumNumberOfTouches:2];
}
Produces the following error message:
-[UIScrollViewPanGestureRecognizer retain]: message sent to deallocated instance 0x1ea38f70
How is this possible? Zombie Analysis says that the gestureRecognizer has been released already?!
Turns out this was an ARC issue... two different solutions for those interested.
#autoreleasepool {
UIPanGestureRecognizer* pgr = [imageTableView panGestureRecognizer];
[pgr setMinimumNumberOfTouches:2];
[pgr setMaximumNumberOfTouches:2];
}
Or
[imageTableView.panGestureRecognizer setMinimumNumberOfTouches:2];
[imageTableView.panGestureRecognizer setMaximumNumberOfTouches:2];
Lesson learned, if it can't be possible.... try ARC as the culprit.

Resources