12

我在某些我認爲很簡單的事情上遇到了一個非常奇怪的錯誤。目標C - 錯誤:'預期類型'

#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 

EDIT 2 **

和ViewController.h文件

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

@interface ViewController : GLKViewController 

@end 
+2

如何定義ViewController? – Wain

+0

這可能會幫助你,類似的問題:http://stackoverflow.com/a/9607607/1422070 – edwardmp

+0

也許在.h文件中你拼錯了類名。 –

回答

34

使用前向聲明:@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)。

+0

我包含了前向聲明,並且我在'.m'文件中導入了頭文件。我仍然得到同樣的錯誤。 你介意多說一點'循環依賴'問題嗎? – user2577959

+0

我的項目有這種循環依賴。我應該如何糾正它? – user2577959

+0

@ user2577959更新了示例 – justin

0

您是否確定在ViewController.h中定義的類接口也拼寫爲「ViewController」?

我做了一個快速測試,在我的項目中創建了ViewController.h類,但在其中重命名爲ViewControllers,並得到與您一樣的錯誤。

+0

只需雙重檢查。一切拼寫正確 – user2577959

+0

你可以發佈ViewController的聲明? – Sid