I am new to SpriteKit and just built my first game. Everything was working great until iOS 7.1. Now, after a few times of advancing to a new level and presenting a new Scene, it crashes. I don't think I am presenting it in an incorrect way:
ZSSMyScene *nextLevel = [[ZSSMyScene alloc] initWithSize:self.size level:self.level score:score];
[self.view presentScene:nextLevel];
I get a EXC_BAD_ACCESS error, and it looks like it is happening on removeSubsprite, but I can't find anywhere in my code that I would be removing a subsprite:
Not sure what other info to provide as this is just an obscure error that seemed to start when I updated to iOS 7.1 SDK.
This appears to be a bug, possibly only with SKShapeNodes.
My solution was to create an SKNode category and call this cleanup method when any node i'm removing has children.
- (void)cleanUpChildrenAndRemove {
for (SKNode *child in self.children) {
[child cleanUpChildrenAndRemove];
}
[self removeFromParent];
}
Related
We are using cocos2d-js to develop an iOS App which can launch different games. So I add an button in the native app viewcontroller and start the game by clicking the button, just like this:
-(void)didClickGame2Btn:(id)sender
{
//加载游戏
cocos2d::Application *app = cocos2d::Application::getInstance();
// Initialize the GLView attributes
app->initGLContextAttrs();
cocos2d::GLViewImpl::convertAttrs();
// Use RootViewController to manage CCEAGLView
RootViewController *rootViewController = [[RootViewController alloc] init];
rootViewController.wantsFullScreenLayout = YES;
[self.navigationController presentViewController:rootViewController animated:YES completion:^{
// IMPORTANT: Setting the GLView should be done after creating the RootViewController
cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)rootViewController.view);
cocos2d::Director::getInstance()->setOpenGLView(glview);
NSString *documentDir = [SEGetDirectories dirDoc];
NSString *wPath = [NSString stringWithFormat:#"%#/GameData/Game2",documentDir];
NSLog(#"document------:%#",documentDir);
std::vector<std::string> searchPathList;
searchPathList.push_back([wPath UTF8String]);
cocos2d::FileUtils::getInstance()->setSearchPaths(searchPathList);
//run the cocos2d-x game scene
app->run();
}];
[[UIApplication sharedApplication] setStatusBarHidden:true];
}
the rootViewController contains the game view. And then we add an button in the game, which is used to exit the game. The click event code of the exit game button likes:
//exit the game and close the view controller
gameEndCallBack:function(sender){
cc.log("director end............");
cc.director.end();
var ojb = jsb.reflection.callStaticMethod("ViewControllerUtils", "dismissCurrentVC");
}
We use the reflection to dismiss the rootViewController:
+(void)dismissCurrentVC
{
UIViewController *currentVC = [ViewControllerUtils getCurrentVC]; //这里获取最顶层的viewcontroller
[currentVC dismissViewControllerAnimated:YES completion:^{
NSLog(#"xxx");
}];
}
Everything is ok when the first time to enter the game, but after dismissing the rootViewController, we try to enter the game again, it crash.
The crash line is in the ScriptingCore::runScript metod and executing the code:
evaluatedOK = JS_ExecuteScript(cx, global, *script, &rval);
And the crash info is "exc_bad_access".
It is much the same problem as this topic, but the approaches in it did not solve the problem.
http://discuss.cocos2d-x.org/t/how-to-destroy-a-cocos-game-on-ios-completely/23805
This problem has been confusing me serveral days, I have no solution for this. Can anyone give me some help?
You can make the app to support multiple games with in the app.
All you have done is required but in addition to that please follow the below instructions.
First of all, cocos provide a singleton instance of cocos2d::Application that can not be restarted again especially in iOS. So the approach of ending the Director cc.director.end(); won't help you.
You should start the application only once by using the function call cocos2d::Application::getInstance()->run(); and next time if you want to start the game layer, you should not call this method again.
Instead, just pause cocos2d::Director::getInstance()->pause(); and resume cocos2d::Director::getInstance()->resume(); the director when you want to stop the game.
In this approach, if you dismiss/dealloc the view-controller instance then you should create the glview cocos2d::GLView instance again without calling the run method.
One more problem is, take care of the delay in loading the new scene. GLView will display the previous game scene for a while. Do a work around that will show blank screen while the new scene is ready.
Hope this will help you.
I'm building a fairly simple game in SpriteKit. This is my first experience with SpriteKit and so far it has gone smoothly. I have gotten to the point now that I want to present a new SKScene when the player completes the game. I'm getting a Bad Access crash that I can't seem to diagnose.
I think I am presenting the scene correctly:
UnlockRockets *scene = [[UnlockRockets alloc] initWithSize:self.scene.size];
[self.view presentScene:scene];
Every time I get the following error on the presentScene: line - Thread 1: EXC_BAD_ACCESS (code=1, address = 0x10)
Looking at the thread trace it appears the crash might be originating at [SKNode isPaused]
Any advice would be great, I'm completely lost on this one.
i think problem in your initWithSize method inside UnlockRockets class
I have had the same issue with SKView present scene, even when scene was absolutely new without any configurations. So I solved it by using this.
myScene *newScene = [myScene sceneWithSize:size];
newScene.scaleMode = SKSceneScaleModeResizeFill;
SKView *currentskView = (SKView*) self.scene.view;
SKScene *currentScene = (SKScene*) self.scene;
[currentScene removeAllChildren];
[currentScene removeFromParent];
[currentskView presentScene:newScene];
also I've noticed that if declare strong reference for the scene - it's works in the way you did, but in that case scene live in memory even if it's invisible, and xCode notifies that there are memory warnings.
I'm trying to solve two problems with MKUserTrackingModeFollowWithHeading in iOS 6:
MKUserTrackingModeFollowWithHeading works briefly, but it's jittery and returns to MKUserTrackingModeFollow almost immediately, especially at high zoom levels.
The app occasionally crashes when repeatedly changing the MKUserTrackingMode: I get EXC_BAD_ACCESS on the main thread, without further information. This is hard to reproduce, but it has happened repeatedly.
Any thoughts on what might be causing this? It feels like a bug, but Apple's own "Maps" app doesn't exhibit this behavior.
In order to isolate the problems, I've created a Single View Application with an MKMapView and a UIToolbar (set up in a .xib), to which I'm adding a MKUserTrackingBarButtonItem. The UIViewController acts as a <MKMapViewDelegate>. Here's the complete implementation code:
#import "ViewController.h"
#implementation ViewController
#synthesize mapView, toolbar;
- (void)viewDidLoad
{
[super viewDidLoad];
// Add MKUserTrackingBarButtonItem to toolbar
MKUserTrackingBarButtonItem *trackButton = [[MKUserTrackingBarButtonItem alloc] initWithMapView:self.mapView];
[toolbar setItems:[NSArray arrayWithObjects:trackButton, nil] animated:YES];
}
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated
{
// Log MKUserTrackingMode change
NSString *modeType = (mode == 0) ? #"None" : ((mode == 1) ? #"Follow" : #"FollowWithHeading");
NSLog(#"MKUserTrackingMode changed to: %#", modeType);
}
#end
This is a bug in MapKit. It can be observed also in Apple Maps using MapKit such as the Find My Friends app. Note that the Apple Maps app is not using MapKit (at least not the same version) thus it's not affected by this bug.
I also do see sporadic EXC_BAD_ACCESS crashes in MapKit. In fact, MapKit related crashes account for the vast majority of my app's crashes. :(
I also noticed that MKUserTrackingModeFollowWithHeading works briefly and it changes to MKUserTrackingModeFollow almost immediately, especially at high zoom levels.
I tried
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mapView.userTrackingMode != MKUserTrackingModeFollowWithHeading) {
[mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading];
}
}
but this creates a forever loop since right after I change to MKUserTrackingModeFollowWithHeading, something changes back to MKUserTrackingModeFollow. It's really annoying because I don't know what keeps changing the tracking mode to MKUserTrackingModeFollow.
Sorry that my answer was not useful, but I posted here to confirm the problem.
I'm having a really frustrating issue with UIGestureRecognizers. They get added fine, but whenever one gets triggered, it crashes with the message EXC_BAD_ACCESS (code=1, address=0xf0000008). I'm adding it in the view controller using the following code:
- (void)handleDrag:(UIGestureRecognizer *)sender {
NSLog(#"%#", sender);
}
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleDrag:)];
[self.windowBar addGestureRecognizer:panGesture];
}
self.windowBar is a UIImageView. I've enabled user interaction on said UIImageView. But whenever I start actually dragging it, it crashes.
I'm not sure if this has anything to do with it, but I'm using the new ARC feature.
What else am I missing? :(
Try running with the Zombies Instrument to detect exactly which zombie (already released) object is being referenced. It will point you to the exact object that the system thinks it should send a message to, but has already been released (with retain count set to 0, and the memory already reassigned).
I am already finishing my game and I am trying to fix some memory issues.
My game has 36 levels and I noticed that when I run it in an iPod, after 20-25 levels my app crashes. I start getting memory warnings and it always crashes when transitioning between scenes.
I have already used instruments to fix every memory leak but this is still happening.
My guess is that cocos is still holding references to old objects.
I would like to find a way to look through the cocos' nodes hierarchy in certain points of my game to make sure everything is ok.
Any idea of how to do that?
I have modified CCTextureCache to log which textures are retained and which others are released, at critical steps in my games, where i force a 'removedUnusedTextures', notably on scene transitions. Whatever you see there should give a hint of where to look in your app. Also, i tend to tag everything with a unique tag, and remember the tags in every class that adds stuff to a CCNode. In the wash (cleanup), i rundown the array of tags, and force remove them.
I ended up doing this:
I added some logic in the CCDirector to "draw" the hierarchy:
-(void) printChildren:(CCNode *)node andLevel:(NSInteger)level {
NSString *tabs = #"";
for (int i=0; i <level; i++) {
tabs = [NSString stringWithFormat:#"%# ", tabs];
}
NSLog(#"%#NODE %#. Children count: %d", tabs, node, node.children.count);
if ( node.children.count == 0 ) {
return;
} else {
for (CCNode *child in node.children) {
[self printChildren:child andLevel:level+1];
}
}
}
-(void) nodeHierarchy
{
NSLog(#"Printing nodeHierarchy! with an stack of %d scenes", [scenesStack_ count]);
for (CCScene *scene in scenesStack_) {
NSLog(#"Scene in stack: %#", [scene class]);
[self printChildren:scene andLevel:0];
}
}
I call nodeHierarchy in the replaceScene method.
It would be great to have a more visual tool, but this worked for me.
Any reason you cannot migrate to SDK 5.0 that has ARC.