您是否尝试过在调试器中单步执行您的代码以准确找出导致崩溃的行?
在我看来,它好像就在这里:
LevelHelperLoader* lh;
finishScreen = [lh spriteWithUniqueName:@"finishScreen"];
您已声明 1h,但您还没有创建它。所以你正在向一个不存在的对象发送消息。
至少,像
LevelHelperLoader* lh = [[LevelHelperLoader alloc] init];
会有帮助的。
粗略浏览一下documentation 会增加更多细节:
LevelHelperLoader* loader = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"];
在文档中,这是一个实例变量 - 这表明 hudLoader 应该是一个实例方法,而不是一个类方法:
- (LevelHelperLoader*) hudLoader;
你应该在你的 hudLoader 初始化器中创建你的 LevelHelperLoader* 实例。
更新
你在评论中说:
在我调用的 hudLayer.mm 的 init 方法中
lh = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"];
在 .h 中我有
LevelHelperLoader* lh;
我不确定这是否是阅读我的答案后的修改。不过这里还有一些想法。
首先,您能否整理一下您的命名约定。类应以大写字母开头。
HudLayer.h
让我们将这个lh 实例变量声明为@interface 中的属性并改进它的名称:
@property (strong) LevelHelperLoader* levelHelper
HudLayer.mm
允许它自动合成或在你的@implementation 中合成为:
@synthesize levelHelper = _levelHelper;
然后在你的 init 方法中
_levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:@"level1"];
而hudLoader 变为
-(LevelHelperLoader*)hudLoader
{
finishScreen = [self.levelHelper spriteWithUniqueName:@"finishScreen"];
return self.levelHelper;
}
然后问问自己,-hudLoader 实际上在做什么?分配给finishscreen 的行? finishscreen 是 iVar 吗?你需要它吗?也许不是。除此之外,-hudLoader 所做的只是返回您已经创建的 LevelHelperLoader 实例。现在您的 iVar 是一个属性,您可以使用点符号属性语法从 gameLayer 访问它,并完全删除 hudLoader:
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!");
}
这让我想知道你是否需要一个 hudLayer 类(也许它正在做其他有用的工作)......看起来你可以直接从 gameLayer 获得你的 levelHelper。
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!");
}
最后,我不建议您逐行遵循此代码,因为我不知道您项目的更广泛背景。但是您确实需要理清类和实例、分配、实例化、本地变量与实例变量之间的混淆。请注意命名约定,以便您知道何时向类或该类的实例发送消息,并且知道何时直接或通过@property(例如self.property)寻址iVar。始终如一。想想一个类实际上为你做什么。