私は2つを持っています view controllers A
とB
であり、両方とも代理としてお互いを持っています。
ヘッダーファイルの先頭でプロトコルを定義し、#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
サンプルをさらに減らし、行にラベルを付けます。
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行がそれらを使用しようとする前に、適切なプロトコルが常に宣言されることがわかります。
#import行の上にプロトコル宣言コードを記述します。
@終わり
@interface classname ---
私はほとんど同じ問題を抱えていて、上の答えのおかげでそれを修正しましたが、少し異なった方法で。
私がしたことは、ヘッダーファイルに#import行afterプロトコル宣言を入れることだけでした。私が助けてくれることを願っています。そして、誰かがこれが何らかの理由で悪いプログラミングであることを知っているなら、私に知らせてください
クラスとプロトコル宣言の間にいくつかの#importsを置くという考えがあまり好きではなかったので、この問題の別の解決策を見つけました。
基本的に、あなたはただ<YourProtocolName>
.hクラスファイルから.mファイルのクラス拡張子まで
.mファイルに追加します
@interface YourClassName () <YourProtocolName>
@end
これが本当に良い習慣であるかどうかはわかりませんが、インポートサイクルを避けるためのよりクリーンなソリューションのように見えます。
ヘッダーファイルではなく、実装ファイルに<BaseViewControllerDelegate>または<BigViewControllerDelegate>を入れてみてください。それが動作します。
インポートの前にプロトコルを移動する修正に従って、問題を修正しました...インポートにデリゲートが含まれていたため、問題が発生していました。
しかし、とにかく、どうしてデリゲートをインポートしたのかと考えました。私はそのプロパティを参照していませんでしたし、そのメソッドを直接呼び出していませんでした(プロトコルが宣言したものです)。
私はデリゲートのインポートをコメントアウトしようとしましたが、エラーが発生した場所を見て、デリゲートをインポートしているときにインポートしているのは実際にデリゲートがインポートしていることを宣言していることを確認しました。 Bをインポートしていましたが、実際に使用していたのはBでした。したがって、Aのインポートをコメントアウトして、Bのインポートを追加しました。