web-dev-qa-db-ja.com

メソッドの戻り値の型を指す「型が必要です」エラー

コンパイルしようとしましたが、実行するたびに、1つのメソッドが奇妙な「タイプを予期しています」エラーをスローします。ヘッダーにメソッドがあります:

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

エラーは、このメソッドの戻り値の型を指しています。 #import "ANObject.h"を使用してANObjectをヘッダーにインポートしましたが、ANObjectは正常にコンパイルされています。

なぜこうなった?

42
Ollie Hirst

これは、ソースファイルがコンパイルされる順序と関係があります。定義される前にメソッドを呼び出すことはできないことを既にご存じでしょう(以下の擬似コードを参照)。

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クラスの上に移動するだけで十分です。

しかし、それをしたくない場合、またはさらに重要なことに、2つのオブジェクト間に循環関係がある場合はどうでしょうか。 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

ああ、今、問題があります。これら2つをサイドバイサイドでコンパイルすることはできません。 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キーワードは、クラスがまもなく登場することをコンパイラに通知します。これは、not#import。ヘッダーファイルをインポートする必要があります。インポートしない場合、クラス内部にはアクセスできません。

@class Ship

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

これは機能せず、Shipは前方宣言であることを示すエラーメッセージで失敗します。 #import "Ship.h"、その後、オブジェクトのインスタンスを作成できるようになります。

93
Steve Rukuts

ヘッダーに循環的な依存関係がある場合、このエラーが発生することがわかりました。このメソッドを宣言する.hファイルがANObject.hにインポートされているかどうかを確認します

54
RENA

基本的に追加します

@class ANObject;

@interfaceの前に!

26
JomanJi

だから、何らかの理由で、パラメータに列挙型を持つメソッドを設定しようとしたときにこのエラーが発生していました。そのようです:

- (void)foo:(MyEnumVariable)enumVariable;

以前はこのように使用していましたが、問題はありませんでしたが、今では使用しました。循環依存関係を確認しましたが、どれも見つかりませんでした。また、タイプミスを複数回確認しましたが、サイコロはありません。最終的に私の問題を解決したのは、変数にアクセスする前に「enum」を追加することでした。そのようです:

- (void)foo:(enum MyEnumVariable)enumVariable;
{
     enum MyEnumVariable anotherEnumVariable;
}
4
olivaresF

変数のタイプのつづりが間違っていたときに、このメッセージが表示されました。以下をご覧ください

例えば.

-(void)takeSimulatorSafePhotoWithPopoverFrame:(GCRect)popoverFrame {

の代わりに.....

-(void)takeSimulatorSafePhotoWithPopoverFrame:(CGRect)popoverFrame {
1
sean808080

通常、このようなエラーが表示されるのは、前の行に追加のかっこや欠落したかっこなどのタイプミスがあるためです。

1
Dave DeLong

ばかげているように聞こえるかもしれませんが、これは間違ったシェル処理または大文字/小文字の間違った使用法です。

1
Yeung

奇妙なことに、過去にインポートの順序を変更するとこれが修正されました...他のすべてのインポートの後にインポートを一番下に移動してみてください。

0
DranoMax