error when returning to game menu after game over [duplicate] - cocos2d-iphone

I'm threeaing some tasks like this :
RootViewController
- (void)viewDidLoad {
[NSThread detachNewThreadSelector:#selector(findSomething) toTarget:self withObject:nil];
}
- (void) findSomething {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
doMoreThings
[pool release];
}
- (void) doMoreThings {
doMoreMoreMoreThings on different objects
}
- (void) foundSomething:(NSFoundThing*)foundObj {
do your stuff
}
oneObject
- (void) doMoreMoreMoreThings {
do things
[self performSelectorOnMainThread:#selector(foundSomething:) withObject:thingFound waitUntilDone:NO];
}
gives
-[KMLParser foundSomething:]: unrecognized selector sent to instance 0x5888080
What is the problem ?

The threading is irrelevant. Some of the code you're not showing us is making it so you are sending the foundSomething: selector to an object that doesn't handle that message. Route the message to an object that does handle it, and your problem will go away.
See also "Unrecognized selector sent to instance".

Related

My CCTargetedAction runs action twice

In cocos2d v3, I could not find something like CCTargetedAction.
It is required in my project, so I copied code from cocos2d v2.
#interface CCTargetedAction : CCActionInterval
/** This is the target that the action will be forced to run with */
#property(readwrite,nonatomic,retain) id forcedTarget;
#property(readwrite,nonatomic,retain) CCActionFiniteTime* action;
/** Create an action with the specified action and forced target */
+(id)actionWithTarget:(id)target
action:(CCActionFiniteTime*)action;
/** Init an action with the specified action and forced target */
-(id)initWithTarget:(id)target
action:(CCActionFiniteTime*)action;
#end
#implementation CCTargetedAction
+(id)actionWithTarget:(id)target
action:(CCActionFiniteTime*)action
{
return [(CCTargetedAction*)[self alloc] initWithTarget:target
action:action];
}
-(id)initWithTarget:(id)target
action:(CCActionFiniteTime*)action
{
self = [super initWithDuration:action.duration];
if(self)
{
self.forcedTarget = target;
self.action = action;
}
return self;
}
-(id)copyWithZone:(NSZone*)zone
{
CCAction *copy = [(CCTargetedAction*) [[self class] allocWithZone: zone]
initWithTarget:_forcedTarget
action:[_action copy]];
return copy;
}
- (void) startWithTarget:(id)aTarget
{
[super startWithTarget:aTarget];
[_action startWithTarget:_forcedTarget];
}
- (void) stop
{
[_action stop];
}
- (void) update:(CCTime) time
{
[_action update:time];
}
#end
But my CCTargetedAction runs action twice.
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CCActionCallBlock* block = [CCActionCallBlock actionWithBlock:^{
CCLOG(#"call block");
}];
CCTargetedAction* action = [CCTargetedAction actionWithTarget:self
action:block];
[self runAction:action];
}
If I touch the screen once, then the log message is output twice.
2014-04-07 22:09:57.439 TargetedActionTest[3924:60b] call block
2014-04-07 22:09:57.455 TargetedActionTest[3924:60b] call block
Why this code runs action twice?
Thank you.
This problem is solved by overwriting -(BOOL)isDone method.
-(BOOL)isDone
{
return [_action isDone];
}
I was referring to this post.
http://cocos2d-x.org/forums/6/topics/39546

Cocos2d. My app crashes in -(void) update:(ccTime)delta method when I use a pre-existing NSMutableArray in a different method -(void)InitCats

guys! Sorry for my bad language.
My app crashes in Update method when I use array which I created in different method InitCats. I create NSMutableArray* Cats and CCSprite* CA in header file in #interface { }.
-(id)init
{
[self InitCats];
[self schedule:#selector(update:) interval:0.0f];
}
-(void)InitCats // This method is work well in -(id)init
{
Cats = [NSMutableArray arrayWithCapacity:NumCats];
for (int a=0; a<NumCats; a++)
{
CCSprite* Cat=[CCSprite spriteWithFile:#"1.png"];
[Cats addObject:Cat];
}
}
-(void) update:(ccTime)delta
{
for (int a=0; a<NumCats; a++)
{
CA = [Cats objectAtIndex:a]; //In this place I have ERROR, app crashes
CA.position = CGPointMake(CA.position.x-1, CA.position.y);
}
}
I guess you pointing to released object. try initialize your array
Cats = [[NSMutableArray alloc] initWithCapacity:NumCats];
and on dealloc
-(void)dealloc
{
[Cats release];
[super dealloc];
}
Ok, the issue is this statement:
Cats = [NSMutableArray arrayWithCapacity:NumCats];
Which will create an auto-released object, however the pointer to this object will be non-nil after it's auto-released, and hence your code is referencing a deallocated object.
You already have a fix:
Cats = [[NSMutableArray alloc] initWithCapacity:NumCats];
and remove the arrayWithCapacity call from within the InitCats method.
(note your capitalization of method and instance variable names is unconventional).

Subclassed CCSpriteBatchNode object is nil

I subclassed CCSpriteBatchNode to make an object that conforms to NSCoding. I was mainly interested in the string name of the CCSpriteBatchNode. After setting break points I realized that the object's string name is always nil. I have a feeling it that my overridden methods might be a contributing factor but I'm not really sure about that. Please see relevant code below:
SpriteBatchNode interface:
#interface SpriteBatchNode: CCSpriteBatchNode {
NSString* batchImageName;
}
SpriteBatchNode implementation:
const NSUInteger defCapacity = 29;
#implementation SpriteBatchNode
#synthesize batchImageName;
+(id)batchNodeWithFile:(NSString*) imageFile
{
return [[self alloc] initWithFile:imageFile capacity:defCapacity];
}
-(id)initWithFile:(NSString *)fileImage {
self = [super initWithFile:fileImage capacity:defCapacity];
if (!self) return nil;
batchImageName = fileImage;
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
NSString* spriteBatchNodeFileImage = [[aDecoder decodeObjectForKey:#"batchImageName"] copy];
self = [super initWithFile:spriteBatchNodeFileImage capacity:defCapacity];
if (!self) return nil;
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:batchImageName forKey:#"batchImageName"];
}
#end
If you aren't using ARC I see two problems here:
batchImageName string is not retained
batchNodeWithFile: is not sending autorelease to the returned instance
Other than that you're using an unusual init style, the common style is this:
if (self)
{
batchImageName = fileImage;
}
return self;
Checking self for nil, then returning nil if it is, is somewhat redundant.

'NSInvalidArgumentException', reason: '-[MenuScene distance]: when replacing a scene

In my code I have made a GameManager singleton which has a method responsible for changing scenes. The first scene I call is the MenuScene after that I replace it with the GameScene. When I do this the Console output shows:
2013-10-07 19:40:55.895 MyGame[56164:a0b] -[MenuScene distance]: unrecognized selector sent to instance 0xb460690
2013-10-07 19:40:56.011 MyGame[56164:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MenuScene distance]: unrecognized selector sent to instance 0xb460690'
From the log, I don't understand why I get -[MenuScene distance] ... because distance is a property of GameScene not MenuScene.
Below is GameManager method for changing scenes:
-(void)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
//NSString* str;
id sceneToRun = nil;
switch (sceneID)
{
case kBeginScene:
sceneToRun = [BeginScene node];
break;
case kGameScene:
sceneToRun = [GameScene node];
break;
case kMenuScene:
sceneToRun = [MenuScene node];
break;
default:
CCLOG(#"Unknown ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil) {
// Revert back, since no new scene was found
currentScene = oldScene;
return;
}
if ([[CCDirector sharedDirector] runningScene] == nil) {
[[CCDirector sharedDirector] runWithScene:sceneToRun];
} else {
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
Also the call to replace scene is in a layer class which is part of the MenuScene. See below:
-(void)startGameScene {
[[GameManager sharedGameManager] runSceneWithID:kGameScene];
}
Please help.
You get this message because the distance message was sent to the MenuScene instance which doesn't have this selector (GameScene does apparently).
So probably somewhere in your scene managing singleton something goes wrong and you still (or already) have a MenuScene instance where you expect to have a GameScene instance.
Add an exception breakpoint in Xcode to see exactly where the message was coming from.
PS: be very careful when managing scenes in a global instance like a singleton. You could easily leak memory if you keep a strong reference to a scene (or any node for that matter) in a global instance/variable. Make sure that every scene has the dealloc method implemented with a log to see that it actually does deallocate.

Get notification's from NSNotificationServer in C++ program

I'm creating a simple C++ application with cmake on Mac.
There is a main in C++ source code file, that create C++ class. Inside this class I'm allocating objective C object, that adding itself to observers in NSNotificationCenter. And I'm not receiving those notifications.
There is a code:
Notifications.h
class LaunchNotification {
public:
LaunchNotification();
virtual ~LaunchNotification();
void StartNotifications();
void StopNotifications();
private:
void *monitor;
};
Notifications.mm
#interface Monitor : NSObject
-(id) init;
-(void) appLaunchedNotification :(NSNotification *) notification;
-(void) appTerminatedNotification :(NSNotification *) notification;
#end
#implementation Monitor
- (id) init
{
self = [super init];
if (self)
{
count = 0;
NSNotificationCenter *notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
[notCenter addObserver : self
selector:#selector(appLaunchedNotification:)
name:NSWorkspaceDidLaunchApplicationNotification
object:nil];
[notCenter addObserver : self
selector:#selector(appTerminatedNotification:)
name:NSWorkspaceDidTerminateApplicationNotification
object:nil];
}
return self;
}
- (void) appLaunchedNotification : (NSNotification *) notification
{
NSString *path = [[notification userInfo]objectForKey: #"NSApplicationPath"];
}
- (void) appTerminatedNotification : (NSNotification *) notification
{
NSString *path = [[notification userInfo]objectForKey: #"NSApplicationPath"];
}
- (void) dealloc
{
NSNotificationCenter *notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
[notCenter removeObserver : self];
[super dealloc];
}
#end
LaunchNotification::LaunchNotification() : monitor(NULL)
{}
LaunchNotification::~LaunchNotification()
{
StopNotifications();
}
void LaunchNotification::StartNotifications()
{
if (NULL == monitor)
{
monitor = [[Monitor alloc] init];
}
}
void LaunchNotification::StopNotifications()
{
if (NULL != monitor)
{
[(id)monitor release];
}
}
You need a run loop because otherwise, NSWorkspace has no mechanism to gain control of your application's thread in order to post notifications.
While the docs say run loops are automatically created, they are not automatically executed. Think about it: how can a thread be simultaneously running your code and running the code in the run loop?
Any tasks that you need to do while you are monitoring the notification centre need to be done in the context of runloop events e.g. on an NSTimer event, or you need a separate thread for that other stuff.