web-dev-qa-db-fra.com

Objectif C - Erreur: 'Attendu un type'

Je reçois une erreur très étrange sur quelque chose que j'aurais pensé être simple.

#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

Pourquoi se demanderait-on si "ViewController" est un type? C'est une classe que j'ai correctement implémentée. Il a également été importé.

EDIT *

Voici la classe ViewController.m si cela peut vous aider.

#import "ViewController.h"

@implementation ViewController

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

@end

EDIT 2 **

et le fichier ViewController.h

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

@interface ViewController : GLKViewController

@end
15
user2577959

Utilisez une déclaration forward: @class ViewController; à la place de #import "ViewController.h". L'importation est généralement inutile dans un autre en-tête d'Objective-C.

Si vous utilisez ViewController dans GameController, vous pouvez ajouter l'importation à GameController.m.

Vous avez probablement une dépendance circulaire.

La méthode de base pour définir une dépendance circulaire est la suivante:

  • GameController.h importations ViewController.h
  • ViewController.h importations GameController.h

Ce qui sera vu en premier dépend de l'ordre de déclaration dans la traduction, mais il faudra évidemment que ce soit le premier, car dans ce cas, les en-têtes sont en désaccord sur ce qui doit venir en premier.

Dans une vraie base de code, vous pouvez #import "ViewController.h" dans de nombreux fichiers sources. Cela crée des dépendances très complexes. Ces dépendances sont en grande partie inutiles dans ObjC - vous pouvez utiliser des déclarations en aval la plupart du temps dans un en-tête (et cela améliorera vos temps de construction).

J'ai donc expliqué le cas le plus simple, mais que se passe-t-il quand 15 en-têtes #import ViewController.h? Eh bien, vous devrez rechercher quel en-tête introduit cette dépendance circulaire pour cette traduction. Si vous ne gérez pas bien les dépendances, vous devrez peut-être parcourir des dizaines (ou des centaines) de fichiers. Parfois, il est plus simple de simplement examiner la sortie prétraitée pour cette traduction (par exemple, le fichier *.m incriminé). Si les dépendances ne sont pas réduites au minimum, cette sortie peut représenter des centaines de milliers de lignes (et vos temps de génération pourraient être 20 fois plus rapides s'il était géré correctement). La complexité de la localisation des dépendances circulaires augmente donc rapidement dans les grandes bases de code; plus vous #import et #include dans les en-têtes. L'utilisation de déclarations anticipées dans les en-têtes (dans la mesure du possible) résout ce problème.

Exemple

Donc, étant donné votre en-tête dans le PO, vous pouvez le réécrire comme suit:

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
...

Ensuite, vous pouvez appliquer le même traitement à ViewController.h (qui importe GameController.h).

36
justin

Êtes-vous certain que l'interface de classe définie dans ViewController.h est également orthographiée "ViewController"?

J'ai fait un test rapide en créant une classe ViewController.h dans mon projet, mais j'ai renommé l'interface ViewControllers à l'intérieur et j'ai obtenu la même erreur que vous.

0
Sid