objective-c - Objective-C - 错误 : 'Expected a type'

标签 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”是否是一种类型?这是我正确实现的类(class)。它也被导入了。

编辑*

如果有帮助,这里是 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

最佳答案

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

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

您可能有循环依赖。

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

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

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

在真实的代码库中,您可以在许多源文件中#import "ViewController.h"。这会产生非常复杂的依赖关系。这些依赖项在 ObjC 中基本上是不必要的——大多数时候您可以在 header 中使用前向声明(这将缩短您的构建时间)。

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

示例

因此,鉴于您在 OP 中的 header ,您可以将其重写为:

游戏 Controller .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

游戏 Controller .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)应用相同的处理。

关于objective-c - Objective-C - 错误 : 'Expected a type' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17624839/

相关文章:

iphone - 将 UIImage 保存到 Core Data 时出错

reactjs - 我如何使用 typescript 在 React 中动态创建 JSX 标签?

ios - Objective-C 中的非重复随机数

javascript - UIWebView 检索链接并导航到它

import - 可以在 Sass 文件的导入语句中使用变量吗?

java - 在eclipse中导入gradle项目时出现问题

c++ - 在 C++ 中组织 header 的最佳方式是什么?

c++ - 将 DLL 链接到 DLL

c++ - 关于 "stdio.h"和 <cstdio> 混合的编译器警告

ios - VoIP 和 Callkit 框架音频问题