目标C - 错误:'预期类型'

时间:2013-07-12 22:13:49

标签: objective-c import header-files forward-declaration circular-dependency

我对一些我认为很简单的事情收到了一个非常奇怪的错误。

#import <Foundation/Foundation.h>
#import "ViewController.h"
#import "GameObject.h"


@interface GameController : NSObject 

@property (strong) GLKBaseEffect * effect;
@property (strong) NSMutableArray * gameObjects;
@property (strong) NSMutableArray * objectsToRemove;
@property (strong) NSMutableArray * objectsToAdd;


+ (GameController *) sharedGameController;
- (void) tick:(float)dt;
- (void) initializeGame: (ViewController*) viewcontroller;//ERROR: EXPECTED A TYPE

- (void) createObject:(Class) objecttype atPoint:(CGPoint)position;
- (void) deleteObject:(GameObject*) object atPoint:(CGPoint)position;
- (void) manageObjects;

@end

为什么会问'ViewController'是否是一个类型?这是我正确实施的课程。它也是进口的。

编辑 *

如果它有帮助,这是ViewController.m类。

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[GameController sharedGameController] initializeGame:self];
}

@end

编辑2 **

和ViewController.h文件

#import <GLKit/GLKit.h>
#import "GameController.h" 

@interface ViewController : GLKViewController

@end

2 个答案:

答案 0 :(得分:37)

使用前瞻声明:@class ViewController;代替#import "ViewController.h"。在Objective-C中的另一个标头中通常不需要导入。

如果您在ViewController中使用GameController,则可以将导入添加到GameController.m。

您可能有循环依赖。

定义循环依赖的基本方法是:

  • GameController.h导入ViewController.h
  • ViewController.h导入GameController.h

首先会看到哪一个取决于翻译中的声明顺序,但显然必须首先考虑,因为在这种情况下,标题不一致必须先出现。

在实际代码库中,您可以在许多源文件中#import "ViewController.h"。这会创建非常复杂的依赖项。 ObjC中很大程度上不需要这些依赖项 - 您可以在标题中大部分时间使用前向声明(这样可以缩短构建时间)。

所以我解释了最简单的情况,但是15个标题#import ViewController.h会发生什么?好吧,你必须追踪哪个标题引入了该翻译的循环依赖。如果您不能很好地管理依赖项,那么您可能需要逐步完成数十(或数百)个文件。有时,最简单的方法是查看该翻译的预处理输出(例如,有问题的*.m文件)。如果依赖关系没有最小化,那么该输出可能是数十万行(如果管理正确,您的构建时间可能会快20倍或更多)。因此,在大型代码库中快速定位循环依赖的复杂性;标头中的#import#include越多。在标题中使用前向声明(如果可能)解决了这个问题。

示例

因此,在OP中给出了标题,您可以将其重写为:

GameController.h

// includes
#import <Foundation/Foundation.h>

// forwards required by this header    
@class GameObject;
@class GLKBaseEffect;
@class ViewController;

// header declarations
@interface GameController : NSObject 

@property (strong) GLKBaseEffect * effect;
@property (strong) NSMutableArray * gameObjects;
@property (strong) NSMutableArray * objectsToRemove;
@property (strong) NSMutableArray * objectsToAdd;


+ (GameController *) sharedGameController;
- (void) tick:(float)dt;
- (void) initializeGame: (ViewController*) viewcontroller;//ERROR: EXPECTED A TYPE

- (void) createObject:(Class) objecttype atPoint:(CGPoint)position;
- (void) deleteObject:(GameObject*) object atPoint:(CGPoint)position;
- (void) manageObjects;

@end

GameController.m

#import "GameController.h"
#import "ViewController.h" // << if you need it in this source
#import "GameObject.h" // << if you need it in this source

@implementation GameController
...

然后你可以对ViewController.h(导入GameController.h)应用相同的处理。

答案 1 :(得分:0)

您确定ViewController.h中定义的类接口也拼写为“ViewController”吗?

我通过在项目中创建ViewController.h类进行了快速测试,但是将界面重命名为ViewControllers并且得到了与您相同的错误。