web-dev-qa-db-ja.com

プロトコル宣言が見つかりません

私は2つを持っています view controllers ABであり、両方とも代理としてお互いを持っています。

ヘッダーファイルの先頭でプロトコルを定義し、#import相手のヘッダーファイル、次の行に沿って2つのエラーが発生しました-

a.h(私が書いた場所)に表示されていた "BDelegate"のプロトコル宣言が見つかりませんB.h(私が書いた場所)に表示されていた "ADelegate"のプロトコル宣言が見つかりません

オンラインで見ると、人々は以前に、ヘッダーファイルを循環的に含めると問題が発生する可能性があると書いていました。彼らは#include代わりに、または@class宣言-

@class A

の代わりに

#import A.h

内部#import B.h

これらのインポートのほぼすべての組み合わせを試してみましたが、@classes、および#includeしかし、警告を取り除くことはできません。また、オンラインのソリューションでは、#importから.mファイルですが、それでも助けにはなりませんでした。理由の一部は、オンラインのソリューションがちょっとあいまいであるということです-それを壊すことができればそれは素晴らしいことです。

これを修正するために何ができるかについての提案はありますか?


-BigViewController.h-

#import "BaseViewController.h"
#include "BaseViewController.h"

@class BigViewController;

@protocol BigViewControllerDelegate
-(void) BigViewController:(BigViewController *) bigView;
@end

@interface BigViewController : UIViewController <BaseViewControllerDelegate>
{    
     //delegate
     id <BigViewControllerDelegate> delegate;

ivars...    
}

@properties...
@end

--------------------------------------------------

-BaseViewController.h-

#<UIKit/UIKit.h>

#import "BigViewController.h"
#include "BigViewController.h"

@class BigViewController;

@protocol BaseViewControllerDelegate
- (void) setParametersWithItemChosen:(Item *) item;
@end

@interface BaseViewController : UIViewController <...BigViewControllerDelegate...>
{

   ivars...

   //delegate
    id <BaseViewControllerDelegate> delegate;
}

@properties...
@end
59
Ak1

サンプルをさらに減らし、行にラベルを付けます。

VC1.h

#import "VC2.h"  // A

@class VC1;

@protocol VC1Delegate // B
@end

@interface VC1 : UIViewController <VC2Delegate> // C
@end

VC2.h

#import "VC1.h"  // D

@class VC2;

@protocol VC2Delegate // E
@end

@interface VC2 : UIViewController <VC1Delegate> // F
@end

何かが#imports VC1.hのときに何が起こるか考えてください:行Aに到達すると、インポートが処理されます。 VC1.hが既にインポートされているため、行Dは何もしません。次に、行Eが処理されます。次に、行Fを使用すると、まだ行Bに到達していないためエラーが発生し、プロトコルが宣言されていません。

次に、何かが#VC2.hをインポートするときに何が起こるかを考えてみましょう:行Dに到達し、インポートが処理されます。 VC2.hはすでにインポートされているため、行Aは何もしません。次に、行Bが処理されます。それからC行、そしてまだE行に至っていないのでエラーが発生し、プロトコルは宣言されていません!

最初のステップは、これらのクラスの両方が本当に互いのデリゲートである必要があるかどうかを再検討することです。サイクルを断ち切ることができれば、おそらくそれが道です。そうでない場合は、ヘッダーを再構築する必要があります。最も簡単な方法は、おそらくデリゲートを独自のヘッダーに入れることです。

VC1Delegate.h

@class VC1;

@protocol VC1Delegate // B
@end

VC1.h

#import "VC1Delegate.h"
#import "VC2Delegate.h"

@interface VC1 : UIViewController <VC2Delegate> // C
@end

VC2Delegate.h

@class VC2;

@protocol VC2Delegate // E
@end

VC2.h

#import "VC1Delegate.h"
#import "VC2Delegate.h"

@interface VC2 : UIViewController <VC1Delegate> // F
@end

ここでインポートをトレースすると、@ interface行がそれらを使用しようとする前に、適切なプロトコルが常に宣言されることがわかります。

101
Anomie

#import行の上にプロトコル宣言コードを記述します。

@プロトコル-----

@終わり

インポート----

@interface classname ---

100
Vinner

私はほとんど同じ問題を抱えていて、上の答えのおかげでそれを修正しましたが、少し異なった方法で。

私がしたことは、ヘッダーファイルに#import行afterプロトコル宣言を入れることだけでした。私が助けてくれることを願っています。そして、誰かがこれが何らかの理由で悪いプログラミングであることを知っているなら、私に知らせてください

37
litov

クラスとプロトコル宣言の間にいくつかの#importsを置くという考えがあまり好きではなかったので、この問題の別の解決策を見つけました。

基本的に、あなたはただ<YourProtocolName> .hクラスファイルから.mファイルのクラス拡張子まで

.mファイルに追加します

@interface YourClassName () <YourProtocolName>
@end

これが本当に良い習慣であるかどうかはわかりませんが、インポートサイクルを避けるためのよりクリーンなソリューションのように見えます。

10

ヘッダーファイルではなく、実装ファイルに<BaseViewControllerDelegate>または<BigViewControllerDelegate>を入れてみてください。それが動作します。

8
coreDeviOS

インポートの前にプロトコルを移動する修正に従って、問題を修正しました...インポートにデリゲートが含まれていたため、問題が発生していました。

しかし、とにかく、どうしてデリゲートをインポートしたのかと考えました。私はそのプロパティを参照していませんでしたし、そのメソッドを直接呼び出していませんでした(プロトコルが宣言したものです)。

私はデリゲートのインポートをコメントアウトしようとしましたが、エラーが発生した場所を見て、デリゲートをインポートしているときにインポートしているのは実際にデリゲートがインポートしていることを宣言していることを確認しました。 Bをインポートしていましたが、実際に使用していたのはBでした。したがって、Aのインポートをコメントアウトして、Bのインポートを追加しました。

3
dawid