Strange Crash, No Debugger Clues - objective-c

I am currently running this Block of code in my Level1.m file, this is the scene for the first level of my game.
#import "BankerL1.h"
#import "GameOverScene.h"
#import "BankerGameWin1.h"
// HelloWorldLayer implementation
#implementation BankerL1Layer
#synthesize label = _label;
#synthesize Banker = _Banker;
#synthesize WalkAction = _WalkAction;
#synthesize MoveAction = _MoveAction;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
BankerL1Layer *layer = [BankerL1Layer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *background = [CCSprite spriteWithFile:#"Ninja Menu Background.png"];
background.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:background z:-1];
CCLabelTTF *Levelcounter = [CCLabelTTF labelWithString:#"Level 1" fontName:#"Marker Felt" fontSize:40];
Levelcounter.position = ccp(winSize.width * 0.80,winSize.height * 0.92);
[self addChild: Levelcounter];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: #"GreenorcSpriteSheet_default.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"GreenorcSpriteSheet_default.png"];
[self addChild:spriteSheet];
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <=6; ++i) {
[walkAnimFrames addObject: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"Greenorc%d.png", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
self.Banker = [CCSprite spriteWithSpriteFrameName:#"Greenorc1.png"];
_Banker.position = ccp(winSize.width/2, (winSize.height/2)-190);
self.WalkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
//[_Banker runAction:_WalkAction];
[spriteSheet addChild:_Banker];
self.isTouchEnabled = YES;
_targets = [[NSMutableArray alloc] init];
}
return self;
}
- (void) onEnter
{
// First, call super if you override this. ALWAYS.
[super onEnter];
[self schedule:#selector(gameLogic:) interval:1.5];
[self scheduleUpdate]; // use this instead of schedule: if it's for an update method.
}
//Implements the Callback function above
-(void)gameLogic:(ccTime)dt {
[self addTarget];
}
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
if (sprite.tag == 1) { // target
[_targets removeObject:sprite];
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:#"You Lose :["];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
} else if (sprite.tag == 2) { // projectile
[_targets removeObject:sprite];
}
}
//Adds the "targets" or in this case enemies, to the scene and spawns/moves them
-(void)addTarget {
CCSprite *target = [CCSprite spriteWithFile:#"seeker.png"
rect:CGRectMake(0, 0, 40, 40)];
target.tag = 1;
[_targets addObject:target];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = target.contentSize.height/2;
int maxX = winSize.height - target.contentSize.height/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;//Randomizes the place it will spawn on X- Axis
// Create the target slightly off-screen along the top edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(actualX, winSize.height + (target.contentSize.height/2));
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 5.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;//Speed is randomized between 2 and 5
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(actualX, -target.contentSize.height/2)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}
//WHEN THE THINGS COLLIDE, THEY DISSAPEAR
- (void)update:(ccTime)dt {
CGSize winSize = [[CCDirector sharedDirector] winSize];
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *target in _targets) {
CGRect targetRect = CGRectMake(
target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
target.contentSize.width,
target.contentSize.height);
BOOL playerHit = FALSE;
for (CCSprite *player in _targets) {
CGRect playerRect = CGRectMake(
player.position.x - (player.contentSize.width/2),
player.position.y - (player.contentSize.height/2),
player.contentSize.width,
player.contentSize.height);
if (CGRectIntersectsRect(playerRect, targetRect)) {
//[targetsToDelete addObject:target];
playerHit = TRUE;
[targetsToDelete addObject:target];
break;
}
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
_targetsDestroyed++;
[_label setString:[NSString stringWithFormat:#""]];
if (_targetsDestroyed > 30) {
GameWinScene *gameWinScene = [GameWinScene node];
_targetsDestroyed = 0;
[[CCDirector sharedDirector] replaceScene:gameWinScene];
} else{
NSString *killcounttext = [NSString stringWithFormat:#"Catches: %i", _targetsDestroyed];
self.label = [CCLabelTTF labelWithString:killcounttext fontName:#"Zapfino" fontSize:20];
_label.color = ccc3(225,225,225);
_label.position = ccp(winSize.width * 0.20,winSize.height * 0.92);
[self addChild:_label];
}
}
if (targetsToDelete.count > 0) {
[targetsToDelete addObject:target];
}
[targetsToDelete release];
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
//[[SimpleAudioEngine sharedEngine] playEffect:#"ProjectileHit.wav"];
}
[targetsToDelete release];
}
-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0
swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
return YES;
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
float bankerVelocity = 320.0/2.0;
CGPoint moveDifference = ccpSub(touchLocation, _Banker.position);
float distanceToMove = ccpLength(moveDifference);
float moveDuration = distanceToMove / bankerVelocity;
if (moveDifference.x < 0) {
_Banker.flipX = NO;
} else {
_Banker.flipX = YES;
}
[_Banker stopAction:_MoveAction];
if (!_Moving) {
[_Banker runAction:_WalkAction];
}
self.MoveAction = [CCSequence actions:
[CCMoveTo actionWithDuration:moveDuration position:touchLocation],
[CCCallFunc actionWithTarget:self selector:#selector(bearMoveEnded)],
nil];
[_Banker runAction:_MoveAction];
_Moving = TRUE;
}
-(void)bearMoveEnded {
[_Banker stopAction:_WalkAction];
_Moving = FALSE;
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
self.Banker = nil;
self.WalkAction = nil;
// don't forget to call "super dealloc"
[super dealloc];
}
#end
The scene starts and everything works fine except as soon as a target is added (this is what I think is happeneing) the game freezes and crashes.
I don't know if the target being added is what is causing the crash, but it seems that whenever it is time for the target to come on, it crashes.
There is nothing in the debugger that says the game crashed, Xcode things the game is still running even though it is frozen. Please help :/ thanks

retain the _targets array in the init method like this: _targets = [[[NSMutableArray alloc] init] retain];

Related

How to add a CCsprite to layer from array

Hi guys I really need some help, I have been stuck in this part of my game for over a week now and I can't seem to get past this issue, So have look at my code below,
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
CCSprite *mole1 = [CCSprite spriteWithFile:#"lightsabericonblue.png"];
[self starCreateCurrentLevel:mole1];
}
return self;
}
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:mole1];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:1];
}
- (void)tryPopMoles:(ccTime)dt {
if(moles.count != 0){
for (CCSprite *mole in moles) {
if (arc4random() % moles.count == 0) {
if (mole.numberOfRunningActions == 0) {
[self popMole:mole];
}
}
}
}else if(moles.count == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)mole {
mole.position = ccp(150, 150);
[self addChild:mole];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end
When I run this code i get the following error, * Assertion failure in -[HelloWorldLayer addChild:z:tag:], /Users/....../libs/cocos2d/CCNode.m:335.
I when i add the child in the init method its fine but I don't want to do that, I want to be able to call the try pop mole which will then call the pop mole based on if there is anymore sprites left in the array, I have a feeling I am missing something or doing something wrong.
UPDATE -
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
CGSize winSize;
int enemyX;
int enemyY;
int randomAngleY;
int randomAngleX;
int winSizeX;
int winSizeY;
int minDuration = 1;
int maxDuration = 4.0;
int rangeDuration;
int actualDuration;
int starCountCurrentLevel;
int test = 0;
#implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
[self starCreateCurrentLevel];
}
return self;
}
-(void)starCreateCurrentLevel{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:3];
}
- (void)tryPopMoles:(ccTime)dt {
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:moles];
for (int randomIndex = tempArray.count -1; randomIndex < tempArray.count; randomIndex--) {
CCSprite * sprite = (CCSprite *)[tempArray objectAtIndex:randomIndex];
//CCSprite *sprite = [tempArray objectAtIndex:randomIndex];
[self popMole:sprite];
NSLog(#"Enemy Added");
[tempArray removeObject:sprite];
}
if([tempArray count] == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)sprite {
winSizeX = winSize.width - sprite.contentSize.width + 25;
winSizeY = winSize.height - 25 - sprite.contentSize.height + 17;
randomAngleX = arc4random() % winSizeX;
randomAngleY = arc4random() % winSizeY;
enemyX = arc4random() % winSizeX ;
enemyY = arc4random() % winSizeY;
rangeDuration = maxDuration - minDuration;
actualDuration = (arc4random() % rangeDuration) + minDuration;
sprite.position = ccp(enemyX, enemyY);
[self addChild:sprite];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end
You're only creating the sprite once, but trying to add it several times. (Remember, these are pointers to objects, so you're always referring to exactly the same sprite.) If you want 10 versions of the same sprite (at different positions, scales, speeds, whatever), you'll need to create the sprite (via the creator method) 10 times. You can do a copy on the original one, or just create it on the fly:
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
//[moles addObject:mole1];
// ^^ You're adding the same sprite (meaning same pointer reference) again and again. Try this instead:
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
Of course, now you don't need to pass mole1 into your method. You may (depending on your need) consider passing in a spriteFrameName or something.

Dealloc gives warnings

I am practicing making a simple app that switches scenes with a scene controller (state manager) class.
I created my scene:
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
GameMenu *layer = [GameMenu node];
[scene addChild: layer];
return scene;
}
-(id)init{
if ((self = [super init])){
self.isTouchEnabled = YES;
CGSize winSize = [[CCDirector sharedDirector] winSize];
gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
gameMenuLabel.position = ccp(winSize.width/2, winSize.height/1.5);
[self addChild:gameMenuLabel];
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"ccTouchesBegan: called from MainMenu object");
[[StateManager sharedStateManager] runSceneWithID:kGamePlay];
}
-(void)dealloc{
[gameMenuLabel release];
gameMenuLabel = nil;
[super dealloc];
}
#end
But I keep getting this warning: https://dl.dropbox.com/u/1885149/Screen%20Shot%202012-10-06%20at%205.23.43%20PM.png (probably not much help, but figured I would link the screenshot.
I think it has something to do with the dealloc. If I comment out the dealloc in my scene, I do not get this warning. Any help would be greatly appreciated, thanks.
This is my statemanager's method for switching scenes:
-(void)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID) {
case kSplashScene:
sceneToRun = [SplashScene node];
break;
case kGameMenu:
sceneToRun = [GameMenu node];
break;
case kGamePlay:
sceneToRun = [GamePlay node];
break;
case kGameOver:
sceneToRun = [GameOver 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];
}
}
You should give a retain property to gameMenuLabel like this
#property (nonatomic, retain) CCLabelTTF* gameMenuLabel; //in .h file
And write this....
self.gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
instead of this...
gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
The problem is that you are giving an autoreleased object to gameMenuLabel and then releasing again that object in the dealloc section. Hence, the crash.

cocos2d ccTintTo, implementing an endless changing color label

Instead of writing all those lines at the init method of HelloWorldLayer :
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
[label runAction:sequence];
I tried to make the label change color forever but got stucked:
I don't know where to place the relavant commands+ dealing with the integers x,y,z
I tried to do the randomize process at the update method,but didn't have any access to the label, any ideas?
// HelloWorldLayer.h
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "cocos2d.h"
#interface HelloWorld : CCLayer
{
CCTintTo* tint1;
CCSequence* sequence1;
// CCLabelTTF* label; even tried property
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
#end
//
// HelloWorldLayer.m
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "HelloWorldScene.h"
#import "MenuScene.h"
integer_t x;
integer_t y;
integer_t z;
#implementation HelloWorld
+(id) scene
{
CCScene* scene = [CCScene node];
CCLayer* layer = [HelloWorld node];
[scene addChild:layer];
return scene;
}
-(id) init
{
if ((self = [super init]))
{
CCLOG(#"init %#", self);
// enable touch input
self.isTouchEnabled = YES;
CGSize size = [[CCDirector sharedDirector] winSize];
// add the "touch to continue" label
CCLabelTTF* label = [CCLabelTTF labelWithString:#"Touch Screen For Awesome" fontName:#"AmericanTypewriter-Bold" fontSize:30];
label.position = CGPointMake(size.width / 2, size.height / 8);
[self addChild:label];
[self schedule:#selector(update:) interval:1/60.0f];
/*
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z];
sequence1 = [CCSequence actions:tint1, nil ];
id goaction=[CCRepeatForever actionWithAction:sequence1];
[label runAction:goaction];
*/
}
return self;
}
-(void) registerWithTouchDispatcher
{
// call the base implementation (default touch handler)
[super registerWithTouchDispatcher];
//[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}
-(void) update:(ccTime)delta
{
x=(integer_t )(CCRANDOM_0_1()*255); y=(integer_t )(CCRANDOM_0_1()*255); z=(integer_t )(CCRANDOM_0_1()*255);
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z ];
sequence1 = [CCSequence actions:tint1, nil ];
[HelloWorld.label runAction:goaction]; //property label not found on object of type 'HelloWorld'
}
// Touch Input Events
-(CGPoint) locationFromTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView: [touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint location = [self locationFromTouches:touches];
CCLOG(#"touch moved to: %.0f, %.0f", location.x, location.y);
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// the scene we want to see next
CCScene* scene = [MenuScene scene];
CCTransitionSlideInR* transitionScene = [CCTransitionSlideInR transitionWithDuration:3 scene:scene];
[[CCDirector sharedDirector] replaceScene:transitionScene];
}
-(void) ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) dealloc
{
CCLOG(#"dealloc: %#", self);
// always call [super dealloc] at the end of every dealloc method
[super dealloc];
}
#end
If you want the tint color to be random for each time, then you cannot use CCTintTo directly inside CCRepeatForever. You need to re-randomize the RGB values for each CCTintTo action. Thus you need to embed the randomization process inside the action by using block. Here is how:
// do this in init method
__block void (^changeTint)(CCNode*) = [[^(CCNode *node) {
GLubyte x = (integer_t)(CCRANDOM_0_1()*255), y = (integer_t)(CCRANDOM_0_1()*255), z = (integer_t)(CCRANDOM_0_1()*255);
[node runAction:[CCSequence actionOne:[CCTintTo actionWithDuration:2 red:x green:y blue:z]
two:[CCCallBlockN actionWithBlock:changeTint]]];
} copy] autorelease];
changeTint(label);
You should look at CCRepeatForever action. As the name implies, it will repeat the action it points to forever. So you should remove your update method where you are changing the colors, and return to the CCSequence code that you had, and embed that in a CCRepeatForever action:
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
CCAction* repeat = [CCRepeatForever actionWithAction:sequence];
[label runAction:repeat];

Mac app - drag and drop files into a menubar application

My inspiration for this project is the Droplr and CloudApp mac menubar applications. I have been attempting to implement the code explained here.
However, when I implement the code, the menubar images disappear. Here is my code to create the status item:
- (id)init {
self = [super init];
if (self != nil) {
// Install status item into the menu bar
NSStatusItem *statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:STATUS_ITEM_VIEW_WIDTH];
_statusItemView = [[StatusItemView alloc] initWithStatusItem:statusItem];
_statusItemView.image = [NSImage imageNamed:#"Status"];
_statusItemView.alternateImage = [NSImage imageNamed:#"StatusHighlighted"];
_statusItemView.action = #selector(togglePanel:);
StatusItemView* dragView = [[StatusItemView alloc] initWithFrame:NSMakeRect(0, 0, 24, 24)];
[statusItem setView:dragView];
[dragView release];
}
return self;
}
This is my view file:
#import "StatusItemView.h"
#implementation StatusItemView
#synthesize statusItem = _statusItem;
#synthesize image = _image;
#synthesize alternateImage = _alternateImage;
#synthesize isHighlighted = _isHighlighted;
#synthesize action = _action;
#synthesize target = _target;
#pragma mark -
- (id)initWithStatusItem:(NSStatusItem *)statusItem {
CGFloat itemWidth = [statusItem length];
CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
self = [super initWithFrame:itemRect];
if (self != nil) {
_statusItem = statusItem;
_statusItem.view = self;
}
return self;
}
#pragma mark -
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
//register for drags
[self registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
}
return self;
}
//we want to copy the files
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
return NSDragOperationCopy;
}
perform the drag and log the files that are dropped
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pboard = [sender draggingPasteboard];
if( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
NSLog(#"Files: %#",files);
}
return YES;
}
#pragma mark -
- (void)drawRect:(NSRect)dirtyRect {
[self.statusItem drawStatusBarBackgroundInRect:dirtyRect withHighlight:self.isHighlighted];
NSImage *icon = self.isHighlighted ? self.alternateImage : self.image;
NSSize iconSize = [icon size];
NSRect bounds = self.bounds;
CGFloat iconX = roundf((NSWidth(bounds) - iconSize.width) / 2);
CGFloat iconY = roundf((NSHeight(bounds) - iconSize.height) / 2);
NSPoint iconPoint = NSMakePoint(iconX, iconY);
[icon compositeToPoint:iconPoint operation:NSCompositeSourceOver];
}
#pragma mark -
#pragma mark Mouse tracking
- (void)mouseDown:(NSEvent *)theEvent {
[NSApp sendAction:self.action to:self.target from:self];
}
#pragma mark -
#pragma mark Accessors
- (void)setHighlighted:(BOOL)newFlag {
if (_isHighlighted == newFlag) return;
_isHighlighted = newFlag;
[self setNeedsDisplay:YES];
}
#pragma mark -
- (void)setImage:(NSImage *)newImage {
if (_image != newImage) {
_image = newImage;
[self setNeedsDisplay:YES];
}
}
- (void)setAlternateImage:(NSImage *)newImage {
if (_alternateImage != newImage) {
_alternateImage = newImage;
if (self.isHighlighted) {
[self setNeedsDisplay:YES];
}
}
}
#pragma mark -
- (NSRect)globalRect {
NSRect frame = [self frame];
frame.origin = [self.window convertBaseToScreen:frame.origin];
return frame;
}
#end
Thanks everyone!
I know this is an old question but perhaps this might help:
Try setting the NSStatusItem *statusItem as a #propery of the class. If you have ARC, the menubar might be getting destroyed right after the init function finishes.

Updating my HUD class through a SceneManager class

I'm doing an iPhone app (game) for University. I'm accessing the HUD class so I can update a label when progress is made through the game. Have I got a bad architecture to do this? Or how can I do it?
HUD Class
#implementation HUD
#synthesize statBar;
#synthesize levelText;
#synthesize label;
#synthesize level;
- (id) init {
if((self = [super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
statBar = [CCSprite spriteWithFile:#"statbar.png"];
statBar.position = ccp(winSize.width/2, winSize.height-10);
levelText = [self createLevelText:10]; // testing purposes
levelText.position = ccp(((winSize.width)-(winSize.width)+20), winSize.height-10);
levelText.color = ccBLACK;
[self addChild:statBar];
[self addChild:levelText];
}
return self; // shouldnt reach this
}
- (CCLabelTTF *) createLevelText:(int)levelNo {
level = [NSString stringWithFormat:#"LVL: %d", levelNo];
label = [CCLabelTTF labelWithString:(NSString*) level fontName:#"CharlemagneStd-Bold.otf" fontSize:10];
//[label setString:(NSString *) level];
return label;
}
#end
ScreenManager Class (Relevant Code)
CCLayer *hudLayer;
int hudTag;
+(void) goPlay
{
hudLayer = [HUD node];
CCLayer *playLayer = [PlayLayer node];
hudTag = playLayer.tag;
[SceneManager goWithHud: playLayer: hudLayer: hudTag];
}
+ (CCScene *) goWithHud:(CCLayer *) playLayer:(CCLayer *) hudLayer:(int)hudTag
{
CCDirector *director = [CCDirector sharedDirector];
CCScene *newScene = [CCScene node];
[newScene addChild: playLayer];
[newScene addChild: hudLayer z:0 tag:hudTag];
if([director runningScene])
[director replaceScene:newScene];
else
[director runWithScene:newScene];
return newScene;
}
+(void)setScoreString:(int *)levelNo:(CCLayer *) hudLayer
{
NSString *string = [NSString stringWithFormat:#"LVL: %d", levelNo];
hudLayer.levelText = string;
}
-(void)updateScore
{
HUD *obj = (HUD *)[self getChildByTag:hudTag];
[obj setScoreString:#"100"];
}