【问题标题】:Possible circular reference problem可能的循环引用问题
【发布时间】:2010-12-09 19:08:10
【问题描述】:

我不是白痴,但头文件有时让我觉得自己像个白痴。我有一个可能过于复杂的设置,它有一个我无法解决的错误。这是我能做到的尽可能简单的细节......

  • 我有一个包含模型类的控制器类。
  • 我有一个 Scene 类来捕捉动作并与控制器通信。
  • 我有一个 Layer 类,它与 Model 类对话以输出 Model 的状态。
  • Scene 类包含仅用于输出的 Layer 类。
  • 场景必须包含由 Cocos2D 框架确定的层。
  • 特定场景类派生自 RootScene 类,该类包含对 Controller 类的引用。
  • 特定的 Layer 类派生自 RootLayer 类,该类包含对 Model 类的引用。
  • 控制器负责创建场景,场景负责创建层。

在创建一个层并将控制器的模型传递给层的模型时出现问题(AScene.m)。我收到“在非结构或联合的情况下请求成员‘模型’”。铸造不起作用,我不知道如何让这些类相互交谈。我认为部分问题可能是 Controller 类包含 Model 类。

Controller.h

#import <Foundation/Foundation.h>

@class Model;
@class AScene;

@interface Controller : NSObject {
    Model *Model;
}
@property (nonatomic, retain) Model *Model;
-(void)runScene;

Controller.m

#import "Controller.h"

#import "Model.h"
#import "AScene.h"

@implementation Controller

@synthesize Model;

- (void)runScene {
    AScene *newScene = [[AScene alloc] init];
    newScene.controller = self;
}

RootScene.h

#import "cocos2d.h"

@class Controller;

@interface RootScene : Scene {
    Controller *controller;
}
@property (nonatomic, retain) Controller *controller;

@end

RootScene.m

#import "RootScene.h"
#import "Controller.h"

@implementation RootScene

@synthesize controller;

- (id) init {
    self = [super init];
    if (self != nil) {
        //
    }
    return self;
}

- (void) dealloc {
    [controller release];
    [super dealloc];
}

@end

AScene.h

#import "RootScene.h"

@class ALayer;
@class Model;

@interface AScene : RootScene {
}

@end

AScene.m

#import "AScene.h"
#import "ALayer.h"
#import "Model.h"

@implementation AScene

- (id) init {
    self = [super init];
    if (self != nil) {
        ALayer *newLayer = [ALayer node];
        newLayer.model = controller.Model; // <-- Request for member 'Model' in something not a stucture or union
        [self addChild:statusScreenLayer];
    }
    return self;
}

- (void) dealloc {
    [super dealloc];
}

@end

RootLayer.h

#import "cocos2d.h"

@class Model;

@interface RootLayer : Layer {
    Model *model;
}
@property (nonatomic, retain) Model *model;

@end

RootLayer.m

#import "RootLayer.h"

#import "Model.h"

@implementation RootLayer

@synthesize model;

- (id) init {
    self = [super init];
    if (self != nil) {
        //
    }
    return self;
}

- (void) dealloc {
    [model release];
    [super dealloc];
}

@end

ALayer.h

#import "RootLayer.h"

@interface ALayer : RootLayer {
}
-(void) draw;

@end

ALayer.m

#import "ALayer.h"

@implementation ALayer

-(void) draw {
    // draw based on state of the model
}

@end

【问题讨论】:

  • 可能存在名称冲突。实例变量通常以小写字母开头,因此类名可能与模型实例变量发生冲突。
  • 你试过了吗:newLayer.model = self.controller.Model ?

标签: objective-c import cocos2d-iphone circular-dependency


【解决方案1】:

您对AScene 的实现没有#import Controller 的标头。

编辑:显式解决方案。

在 AScene.m 中添加:

#import "Controller.h"

【讨论】:

  • Controller.h在AScene的父类中导入:RootScene。
  • 类不能导入任何东西。头文件由实现文件或其他头文件导入。这就是我的回答的意思:AScene 的实现文件(“AScene.m”)不直接或间接地导入“Controller.h”。
  • @Philip,要完成您认为正在发生的事情,您可以将 RootScene.h 中的 @class Controller; 替换为 #import "Controller.h"。通常,最好的做法是尽量减少标头中的导入,但在这种情况下,子类可能应该具有相同的导入。由于它在两个地方都使用,所以只需将其从 .m 文件移至 .h 文件即可。
【解决方案2】:

尼古拉似乎是对的。除此之外,最佳实践将规定属性(如 ivars)不应以大写字母开头。你只是在寻求伤害。改用这些:

Controller.h

@interface Controller : NSObject {
    Model *model;
}
@property (nonatomic, retain) Model *model;

Controller.m

@synthesize model;

【讨论】:

  • “你只是在寻求伤害。”以什么方式?编译器或 Objective-C 是否期望有小写的 ivars?
  • 这是开发者的期望。如果你是唯一一个查看你的代码的开发者,你可以做你想做的事。但你不是。你共享代码,所以你应该使用别人理解的样式。
  • 正确。假设以大写字母开头表示类、结构等,并且方法、ivars 和属性以小写字母开头。这实际上是大多数编程语言的一种趋势,所以每当你发布代码让别人帮助你解决问题时,他们很可能会立即被这个选择弄糊涂。 (还要注意这个网站上的降价如何呈现Model *ModelModel *model。)此外,使用相同的名称和大写更容易出错——在我的书中,甚至Model *MyModel 会更可取。但是,我有强烈的意见。 :-)
  • 感谢您的信息。非常感谢。
猜你喜欢
  • 2011-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
相关资源
最近更新 更多