【问题标题】:Objective C - Error: 'Expected a type'目标 C - 错误:“预期类型”
【发布时间】:2013-07-11 13:58:07
【问题描述】:

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

#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

【问题讨论】:

  • ViewController 是如何定义的?
  • 这可能会帮助你,类似的问题:stackoverflow.com/a/9607607/1422070
  • 可能在 .h 文件中你拼错了类名。
  • @GradyPlayer 为什么,它已经包含在内了? #import "ViewController.h"无需转发声明。
  • @DavidRönnqvist 当然不需要名为 ViewController.h 的文件包含 ViewController 类的接口

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


【解决方案1】:

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

如果您在GameController 中使用ViewController,则可以将导入添加到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)。

【讨论】:

  • 我包含了前向声明,并将标题导入到“.m”文件中。我仍然得到同样的错误。您介意再解释一下“循环依赖”问题吗?
  • 我的项目有这种循环依赖。我应该如何去纠正它?
  • 所以我将所有导入更改为类前向声明​​,错误消失了。当我这样做时到底发生了什么?是否建议这是我处理所有类导入的方式?
  • @user2577959 标头中的转发比导入要好得多。在某些情况下,您将需要导入(例如,您派生的类必须是可见的)。 @class ViewController 的前向声明只是告诉编译器“有一个名为 ViewController 的 objc 类型”,一旦它知道它就不需要查看类声明。如果你想在翻译中创建使用 ViewController 的界面,那么你导入。
  • @user2577959:这是基本问题:当您编写#import something 时,编译器实质上会获取something 的内容并将其复制粘贴到正在编译的文件中。但是当两个文件都 #import 彼此时,这是不可能的,因为一个必须先于另一个,所以其中一个最终会失望,你会得到一个错误。
【解决方案2】:

你确定ViewController.h内部定义的类接口也拼写为“ViewController”吗?

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

【讨论】:

  • 你能发布 ViewController 的声明吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2017-08-24
  • 2014-09-10
  • 1970-01-01
相关资源
最近更新 更多