Цель 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

ИЗМЕНИТЬ 2 **

и файл ViewController.h

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

@interface ViewController : GLKViewController

@end

Ответ 1

Используйте форвардное объявление: @class ViewController; вместо #import "ViewController.h". Обычно импорт не нужен в другом заголовке в Objective-C.

Если вы используете ViewController в GameController, вы можете добавить импорт в GameController.m.

У вас, вероятно, есть круговая зависимость.

Основной способ определения циклической зависимости:

  • GameController.h import ViewController.h
  • ViewController.h import 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).

Ответ 2

Вы уверены, что интерфейс класса, определенный внутри ViewController.h, также записан как "ViewController"?

Я сделал быстрый тест, создав класс ViewController.h в моем проекте, но переименовал интерфейс в ViewControllers внутри него и получил ту же ошибку, что и вы.