Ошибка «Ожидаемый тип», указывающая на тип возвращаемого значения метода - PullRequest
42 голосов
/ 12 ноября 2011

Я пытался скомпилировать, но каждый раз, когда я это делаю, один метод выдает странную ошибку «ожидаемый тип». У меня есть метод в шапке:

-(ANObject *)generateSomethingForSomethingElse:(NSString *)somethingElse;

Ошибка указывает на тип возвращаемого значения для этого метода. Я импортировал ANObject в заголовок, используя #import "ANObject.h", а ANObject прекрасно компилируется ..

Почему это происходит?

Ответы [ 8 ]

93 голосов
/ 22 ноября 2011

Это связано с порядком компиляции исходных файлов. Возможно, вы уже знаете, что не можете вызвать метод до его определения (см. Ниже псевдокод):

var value = someMethod();

function someMethod()
{
    ...
}

Это может вызвать ошибку во время компиляции, поскольку someMethod () еще не определен. То же самое относится и к классам. Классы компилируются один за другим компилятором.

Итак, если вы представляете, что все классы помещаются в гигантский файл перед компиляцией, вы, возможно, уже сможете увидеть проблему. Давайте посмотрим на Ship и BoatYard класс:

@interface BoatYard : NSObject
@property (nonatomic, retain) Ship* currentShip;
@end

@interface Ship : NSObject
@property (nonatomic, retain) NSString* name;
@property (nonatomic, assign) float weight;
@end

Еще раз, поскольку класс Ship еще не определен, мы еще не можем обратиться к нему. Решение этой конкретной проблемы довольно просто; измените порядок компиляции и скомпилируйте. Я уверен, что вы знакомы с этим экраном в XCode:

Но знаете ли вы, что вы можете перетаскивать файлы вверх и вниз в списке? Это меняет порядок компиляции файлов. Поэтому просто переместите класс Ship над классом BoatYard, и все будет хорошо.

Но что, если вы не хотите этого делать или, что более важно, что, если между двумя объектами существует круговая связь? Давайте увеличим сложность этой диаграммы объекта, добавив ссылку на текущий BoatYard, в котором находится Ship:

@interface BoatYard : NSObject
@property (nonatomic, retain) Ship* currentShip;
@end

@interface Ship : NSObject
@property (nonatomic, retain) BoatYard* currentBoatYard;
@property (nonatomic, retain) NSString* name;
@property (nonatomic, assign) float weight;
@end

О, дорогой, теперь у нас проблема. Эти два не могут быть скомпилированы бок о бок. Нам нужен способ сообщить компилятору, что класс Ship * действительно существует. И именно поэтому ключевое слово @class так удобно.

Чтобы выразить это в терминах непрофессионала, вы говорите: "Поверь мне, мужик, Ship действительно существует, и ты это скоро увидишь". Чтобы сложить все вместе:

@class Ship;

@interface BoatYard : NSObject
@property (nonatomic, retain) Ship* currentShip;
@end

@interface Ship : NSObject
@property (nonatomic, retain) BoatYard* currentBoatYard;
@property (nonatomic, retain) NSString* name;
@property (nonatomic, assign) float weight;
@end

Теперь компилятор знает, как он компилирует BoatYard, что вскоре появится определение класса Ship. Конечно, если этого не произойдет, компиляция все равно будет успешной.

Однако все ключевое слово @class сообщает компилятору о том, что класс скоро появится. Это , а не замена #import. Вы все равно должны импортировать файл заголовка, иначе у вас не будет доступа ни к одному из внутренних компонентов класса:

@class Ship

-(void) example
{
    Ship* newShip = [[Ship alloc] init];
}

Это не может работать и завершится ошибкой с сообщением об ошибке, в котором говорится, что Корабль является предварительным объявлением. После того, как вы #import "Ship.h", вы сможете создать экземпляр объекта.

54 голосов
/ 06 февраля 2012

Я обнаружил, что эта ошибка возникает, когда существует круговая зависимость от заголовков. Проверьте, импортирован ли файл .h, где вы объявляете этот метод, в ANObject.h

26 голосов
/ 03 января 2013

Вы в основном добавляете

@class ANObject;

до @interface!

4 голосов
/ 30 января 2013

Итак, по какой-то причине я получаю эту ошибку при попытке установить метод с типом enum в параметрах. Вот так:

- (void)foo:(MyEnumVariable)enumVariable;

Раньше я использовал его таким образом, и у меня никогда не было проблем, но теперь я сделал это. Я проверил круговую зависимость и не смог найти ни одной. Я также проверил на наличие опечаток несколько раз и никаких кубиков. В итоге моя проблема была решена добавлением enum до того, как я захотел получить доступ к переменной. Вот так:

- (void)foo:(enum MyEnumVariable)enumVariable;
{
     enum MyEnumVariable anotherEnumVariable;
}
1 голос
/ 07 июня 2013

Это может звучать глупо, но неправильный обстрел или неправильное использование прописных / строчных букв неправильный регистр это.

1 голос
/ 11 января 2013

Я получил это сообщение, когда тип переменной был написан с ошибкой.См. Ниже этого ниже

например

-(void)takeSimulatorSafePhotoWithPopoverFrame:(GCRect)popoverFrame {

вместо .....

-(void)takeSimulatorSafePhotoWithPopoverFrame:(CGRect)popoverFrame {
1 голос
/ 12 ноября 2011

Обычно, когда я вижу такую ​​ошибку, это потому, что у меня есть опечатка в предыдущей строке, например, лишние или отсутствующие скобки или что-то в этом роде.

0 голосов
/ 11 января 2017

Как ни странно, изменение порядка моего импорта исправило это в прошлом ... Попробуйте переместить импорт в нижнюю часть после всех остальных импортов.

...