Подтвердить что ты не робот

Objective-C заголовочный файл не распознает пользовательский объект как тип

Я работаю над игрой для iPad, используя cocos2d, которая включает в себя доску, наполненную различными типами плиток. Я создал собственный класс под названием Tile как общий шаблон для фрагментов и несколько подклассов Tile, которые имеют разные свойства и методы. Я также создал класс под названием Board, который, среди прочего, отслеживает расположение всех фрагментов с использованием специальной системы координат.

По какой-то причине в классе Board компилятор, похоже, не распознает Tile как тип объекта, хотя я добавил #import "Tile.h" в начало файла.

Вот соответствующий код (просто спросите, есть ли другие части кода, который вы хотите увидеть):

Tile.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "Board.h"

@interface Tile : NSObject

-(void) updateNeighbors;

@property (nonatomic, retain) CCSprite* sprite;
@property (assign) CGPoint coords;
@property (assign) CGPoint positionInPoints;
@property (nonatomic, retain) NSMutableArray *neighbors;

@end

Board.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "Tile.h"

@interface Board : NSObject

+(Board*)sharedBoard;

- (void) putTile: (Tile*) tile AtIndex: (CGPoint) index; //<-- error here!
- (void) replaceTileAtIndex: (CGPoint) index1 WithTileAtIndex: (CGPoint) index2;
- (Tile*) tileAtIndex: (CGPoint) index; //<-- error here!
- (void) populate;

@property (nonatomic, retain) NSMutableArray *tiles;
@property (nonatomic, retain) NSString *type;
@property (assign) CGPoint size;

@end

Этот код даже не будет создан, и я получаю следующее сообщение об ошибке:

Ожидаемый '(' before 'Tile'

Если я изменяю тип от (Tile*) до (NSObject*), он исправляет ошибку, что заставляет меня думать, что Tile не распознается как тип объекта.

Я искал через Google и этот сайт и не могу понять, почему это происходит.


Update

Неверная ошибка; легко исправить.

Как вы все указали, проблема в том, что два файла заголовка импортируют друг друга, что недопустимо. На данный момент я исправил эту проблему, перемещая оператор #import "Board.h" в Tile.m, так как он не нужен в файле заголовка. Позже, если я решит использовать Board в файле Tile.h, я буду использовать перекрестные ссылки (@class Board;), как это было предложено несколькими из них.

Еще раз спасибо!

4b9b3361

Ответ 1

Это классическая проблема с заголовками, импортирующими заголовки. У вас есть круг здесь: Tile.h импортирует Board.h, который импортирует Tile.h. Это смущает компилятор - он застревает в цикле.

Вы решаете это, не импортируя заголовки в заголовки. Однако вам все равно нужно сообщить компилятору о Tile. В Board.h сделайте "forward declaration" класса:

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@class Tile;    // Dear compiler, 
                // Tile is a class that I will need to refer 
                // to in this file. Please consider it to be a 
                // type; I promise it'll be defined at runtime. 
                // Sincerely, stephenalexbrowne

@interface Board : NSObject
//etc.

Это гарантирует компилятору, что существует класс под названием Tile, который будет существовать во время выполнения; вы можете ссылаться на это имя в остальной части своего заголовка. В вашей реализации для Board вы импортируете Tile.h. Это позволит компилятору увидеть методы и свойства, связанные с классом Tile, где они необходимы.

Аналогично, переместите #import "Board.h" в Tile.m. Поскольку вы не имеете в виду класс Board в Tile.h, вам не нужно делать декларацию вперед.

В общем, лучше всего импортировать заголовки классов только в файлы реализации, где они необходимы. Рамочные заголовки, поскольку они никогда не будут вызывать цикл с вашим кодом, могут и - потому что вам нужно ссылаться на многие из объявленных в них классов - должны быть импортированы в ваши заголовки.

Ответ 2

Два файла не могут импортировать друг друга. Вам нужно перенести директивы импорта в файлы реализации, а вместо этого просто переслать-объявить классы в заголовках (например, @class Tile; в Board.h).

Причина, по которой циклический импорт не работает, заключается в том, что #import буквально включает текст из импортированного файла на месте. Но это также гарантирует, что текст из файла будет включен только один раз, чтобы избежать дублирования деклараций. Поэтому, когда Tile.h говорит, что текст из Board.h должен идти до него, а Board.h говорит, что текст из Tile.h должен идти до него, там буквально ничего не может сделать компилятор - одному из них нужно идти во-первых, и этот файл будет жаловаться, потому что он ожидал, что он уже будет там.

Ответ 3

Это не проблема, но что произойдет, если вы удалите "#import" Board.h "из файла Tile.h". У вас может возникнуть проблема с круговой ссылкой