Ios 从Obj-C中的其他类访问实例方法

Ios 从Obj-C中的其他类访问实例方法,ios,objective-c,xcode,methods,levelhelper,Ios,Objective C,Xcode,Methods,Levelhelper,首先,我使用的是游戏引擎LevelHelper 有人知道从另一个类访问实例化的LevelHelperhelper类的正确方法吗 例如: 我有我的主要gameLayer类和hudLayer类。正在导入hudLayer类,并在gameLayer类中实例化。但是,我需要能够使用gameLayer类访问和操作hudLayer类中加载的sprite 建议我使用LevelHelperhelper实例方法。因此,我在hudLayer类中创建实例方法,然后在init方法中调用它来加载精灵。我尝试将此方法用作实例

首先,我使用的是游戏引擎
LevelHelper

有人知道从另一个类访问实例化的
LevelHelper
helper类的正确方法吗

例如: 我有我的主要
gameLayer
类和
hudLayer
类。正在导入
hudLayer
类,并在
gameLayer
类中实例化。但是,我需要能够使用
gameLayer
类访问和操作
hudLayer
类中加载的
sprite

建议我使用
LevelHelper
helper实例方法。因此,我在hudLayer类中创建实例方法,然后在
init
方法中调用它来加载精灵。我尝试将此方法用作实例方法,但出现了一个错误,称为unrecognized selector

+[hudLayer hudLoader];
如果我尝试将该方法用作类方法,则会出现
EXC\u BAD\u ACCESS
错误

我似乎找不到解决办法

我的代码:

+(LevelHelperLoader*)hudLoader;
  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }
  LHSprite* finishScreen;
#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

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

+(LevelHelperLoader*)hudLoader;
  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }
  LHSprite* finishScreen;
#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

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

+(LevelHelperLoader*)hudLoader;
  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }
  LHSprite* finishScreen;
#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

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

+(LevelHelperLoader*)hudLoader;
  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }
  LHSprite* finishScreen;
#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

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

+(LevelHelperLoader*)hudLoader;
  +(LevelHelperLoader*)hudLoader
    {
       LevelHelperLoader* lh;
       finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
        return lh;
    }
  LHSprite* finishScreen;
#import hudLayer.h

  -(id) init {
       [self retrieveRequiredObjects];

    }

  -(void) retrieveRequiredObjects {
        finishScreen = [[hudLayer  hudLoader] spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }
注意:这段代码只是为了确保我的逻辑和实现是正确的


非常感谢您的帮助。

您是否尝试在调试器中单步执行代码,以准确查找导致崩溃的行

在我看来,它似乎就在这里:

   LevelHelperLoader* lh;
   finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
您已声明1h,但尚未创建它。因此,您正在向一个不存在的对象发送消息

至少是这样

   LevelHelperLoader* lh = [[LevelHelperLoader alloc] init];
会有帮助的

粗略地看一眼会添加更多细节:

   LevelHelperLoader* loader = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 
在文档中,这是一个实例变量-这表明hudLoader应该是一个实例方法,而不是类方法:

- (LevelHelperLoader*) hudLoader;
您应该在hudLoader初始化器中创建LevelHelperLoader*实例

更新

你在评论中说:


我调用的hudLayer.mm的init方法的内部

在我的

我不确定这是不是因为读了我的答案。然而,这里还有一些想法

首先,你能整理一下你的命名习惯吗。课程应该以大写字母开始

HudLayer.h

@interface  
@property (strong) Hudlayer* hudLayer;  
@end
@interface  
@property (strong) LevelHelperLoader* levelHelper;
@end
让我们将此
lh
实例变量声明为@interface中的属性,并改进其名称:

@property (strong) LevelHelperLoader* levelHelper
HudLayer.mm

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

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

 -(void) retrieveRequiredObjects {
        finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }
允许它自动合成或在@implementation中合成为:

@synthesize levelHelper = _levelHelper;
然后在init方法中

 _levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 
并且
hudLoader
成为

 -(LevelHelperLoader*)hudLoader
   {
       finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
        return self.levelHelper;
    }
然后问问自己,
-hudLoader
到底在做什么?分配给
完成屏幕的行
finishscreen
是iVar吗?你需要它吗?也许不是。除此之外,
-hudLoader
所做的就是返回已经创建的LevelHelperLoader实例。既然您的iVar是一个属性,您就可以使用点符号属性语法从gameLayer访问它,并删除
hudLoader

GameLayer.h

@interface  
@property (strong) Hudlayer* hudLayer;  
@end
@interface  
@property (strong) LevelHelperLoader* levelHelper;
@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!");
    }
-(id) init {
        _levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 
       [self retrieveRequiredObjects];
    }

 -(void) retrieveRequiredObjects {
        finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
        NSAssert(finishScreen!=nil, @"Couldn't find the menu!");
    }
这让我想知道您是否需要一个hudLayer类(也许它正在做其他有用的工作)。。。看起来您可以直接从gameLayer获得levelHelper

GameLayer.h

@interface  
@property (strong) Hudlayer* hudLayer;  
@end
@interface  
@property (strong) LevelHelperLoader* levelHelper;
@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!");
    }
-(id) init {
        _levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"]; 
       [self retrieveRequiredObjects];
    }

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

最后,我不是建议您逐行遵循此代码,因为我不知道您项目的更广泛背景。但您确实需要理清类和实例、分配、实例化、局部变量和实例变量之间的混淆。请注意命名约定,以便您知道何时向类或该类的实例发送消息,以及何时直接或通过@property(例如self.property)寻址iVar_。保持一致。想想一门课实际上为你做了什么

在hudLayer.mm的init方法内部,我调用lh=[[LevelHelperLoader alloc]initWithContentOfFile:@“level1”];在.h中,我有LevelHelperLoader*lh;谢谢你的帮助,我会做出你建议的改变,看看它是如何工作的。在我的GameLayer.m中,我根据角色位置移动视图,因此如果我在该层上有hud,hud将被移出视图。为了解决这个问题,我为游戏中应该始终显示在屏幕上的资产创建了单独的类。但是,当加载了GameLayer.m的精灵出现问题时,我需要对加载在HudLayer.m中的精灵进行更改。因此,为了做到这一点,我需要GameLayer能够访问这些精灵,然后在HudLayer中更改它们。我还想到了使用NSUserDefaults更改布尔值并将其保存在GameLayer.h中,然后让HudLayer不断加载并检查布尔值,但我不确定这是否对我的知识节约非常有效,因为我可能是一个资源消耗者。