0

First off, I am using the game engine LevelHelper.

Does anyone know the proper way to access an instanced LevelHelper helper class from another class?

For example: I have my main gameLayer class and a hudLayer class. The hudLayer class is being imported and instanced in the gameLayer class. However i need to be able to access and manipulate the sprites that are loaded in the hudLayer class with gameLayer class.

I was recommended to use the LevelHelper helper instance method. So i create the instance method inside of my hudLayer class, and then call it inside of my init method to load the sprites. I tried using this method as an instance method and i get an error saying unrecognized selector

+[hudLayer hudLoader];

If i try using the method as a class method i get an EXC_BAD_ACCESS Error.

I cant seem to find a solution.

My code:

hudLayer.h :

+(LevelHelperLoader*)hudLoader;

hudLayer.mm :

  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }

gameLayer.h :

  LHSprite* finishScreen;

gameLayer.mm :

#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

  -(void) retrieveRequiredObjects {
        finishScreen = [[hudLayer  hudLoader] spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }

Note: This code is just to make sure my logic and implementation of this is correct.

Any help is appreciated, thanks.

Arun
  • 3,406
  • 4
  • 30
  • 55

1 Answers1

2

Have you tried stepping through your code in the debugger to find exactly which line causes the crash?

To me it looks as if it is here:

   LevelHelperLoader* lh;
   finishScreen = [lh spriteWithUniqueName:@"finishScreen"];

You have declared 1h, but you haven't created it. So you are sending a message to a non-existent object.

At very least, something like

   LevelHelperLoader* lh = [[LevelHelperLoader alloc] init];

would help.

A cursory glance at the documentation adds more detail:

   LevelHelperLoader* loader = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 

In the docs, this is an instance variable - which suggests that hudLoader should be an instance method, not a class method:

- (LevelHelperLoader*) hudLoader;

and you should create your LevelHelperLoader* instance in your hudLoader initialiser.

update

You say in your comment:

inside of my init method for hudLayer.mm i call

    lh = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 

and in the .h i have

    LevelHelperLoader* lh; 

I am not sure if this is modifications since reading my answer or not. However here are some more thoughts.

Firstly can you sort out your naming conventions. Classes should start with Capitals.

HudLayer.h

Let's declare this lh instance variable as a property in your @interface and improve it's name:

@property (strong) LevelHelperLoader* levelHelper

HudLayer.mm

Allow it to be auto-synthesized or synthesize in your @implementation as:

@synthesize levelHelper = _levelHelper;

Then in your init method

 _levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 

and hudLoader becomes

 -(LevelHelperLoader*)hudLoader
   {
       finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
        return self.levelHelper;
    }

but then ask yourself, what is -hudLoader actually doing? The line that assigns to finishscreen? Is finishscreen an iVar? Do you need it? Perhaps not. Aside from that, all -hudLoader is doing is returning your already-created instance of LevelHelperLoader. Now that your iVar is a property you can access this from gameLayer using dot-notation property syntax, and remove hudLoader altogether:

GameLayer.h

@interface  
@property (strong) Hudlayer* hudLayer;  
@end

GameLayer.m

-(id) init {
       _hudLayer = [[Hudlayer alloc] init];
       [self retrieveRequiredObjects];
    }

 -(void) retrieveRequiredObjects {
        finishScreen = [self.hudLayer.levelHelper spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }

This makes me wonder whether you need a hudLayer class at all (maybe it is doing other useful work)... it looks as if you can get at your levelHelper directly from gameLayer.

GameLayer.h

@interface  
@property (strong) LevelHelperLoader* levelHelper;
@end

GameLayer.m

-(id) init {
        _levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 
       [self retrieveRequiredObjects];
    }

 -(void) retrieveRequiredObjects {
        finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }

To conclude, I am not suggesting you follow this code line-for-line because I have no idea the broader context of your project. But you do need to sort out your confusion between classes and instances, allocation, instantiation, local vs instance variables. Please take care with naming conventions so that you know when you are sending a message to a Class or an instance of that class, and you know when you are addressing an iVar _directly or via a @property (eg self.property). Be consistent. And think about what a class is actually doing for you.

foundry
  • 31,615
  • 9
  • 90
  • 125
  • inside of my init method for hudLayer.mm i call lh = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; and in the .h i have LevelHelperLoader* lh; – user1998942 Jan 22 '13 at 04:52
  • Thank you for the help i will make the changes you suggest and see how it works. In my GameLayer.m I am moving the view based on a characters position so if i had the hud on this layer the hud would be moved out of view. To counteract this i created separate classes for the assets in the game that should always be shown on the screen. However i need changes to be applied to sprites that are loaded in HudLayer.m when something happens to a sprite that is loaded with GameLayer.m. So in order to do this i needed GameLayer to be able to access these sprites and which then changes them in HudLayer. – user1998942 Jan 22 '13 at 06:38
  • I also had the idea of using NSUserDefaults to change a boolean and save it with GameLayer.h and then have HudLayer continuously load and check the boolean, but im not sure if this is very efficient as to my knowledge saving NSUserDefaults can be a resource hog. – user1998942 Jan 22 '13 at 06:59