找不到协议声明

时间:2011-06-22 23:04:18

标签: objective-c cocoa-touch protocols

我有两个view controllers AB,他们彼此都是代表。

除了在头文件的开头定义协议和#import另一个头文件之外我什么都没做的时候,我得到了两个错误 -

  

找不到“BDelegate”的协议声明,它正在显示   A.h(我写的地方)无法找到协议声明   “ADelegate”,在B.h(我写的地方)中展示了

在网上看,人们早些时候写过,包含头文件的循环包含可能导致问题。他们建议使用#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

6 个答案:

答案 0 :(得分:101)

让我进一步减少样本,并标记行:

<强> 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行,然后处理导入时会发生什么。 D行无效,因为VC1.h已经导入。然后处理E行。然后是F行,我们得到一个错误,因为我们还没有到B行,所以没有声明协议!

然后考虑当#imports VC2.h时会发生什么:它到达D行,然后处理导入。 A行无效,因为VC2.h已经导入。然后处理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行试图使用它们之前声明适当的协议。

答案 1 :(得分:100)

在#import行上面写协议声明代码 e.g。

@protocol -----

@end

import ----

@interface classname ---

答案 2 :(得分:37)

我遇到了几乎相同的问题,由于上面的答案,我修复了它,但方式略有不同。

我所做的就是在头文件中将#import行放在协议声明之后。 希望我能帮忙。如果有人因为某些原因知道这是糟糕的编程,请告诉我

答案 3 :(得分:10)

我找到了另一个解决这个问题的方法,因为我并不喜欢在类和协议声明之间只有一些#imports的想法。

基本上你只需将<YourProtocolName>从.h类文件移动到.m文件中的类扩展名

所以在.m文件中添加

@interface YourClassName () <YourProtocolName>
@end

我不知道这是不是一个好的做法,但它看起来像是一个更清洁的解决方案,以避免进口周期。

答案 4 :(得分:8)

尝试把&lt; BaseViewControllerDelegate&gt;或者&lt; BigViewControllerDelegate&gt;在实现文件而不是头文件。它会工作。

答案 5 :(得分:3)

我在导入之前遵循了移动协议的修复程序并修复了问题...导入包含了委托,因此导致了问题。

但后来我想,为什么我还要导入代表呢?我没有引用它的属性,我没有直接调用它的任何方法(这是协议声明的用途)。

我尝试评论代理的导入并查看错误出现的位置,并发现我导入委托时导入的内容实际上是代理导入的声明,即我导入A(也是我的代理人) ),A正在导入B,我实际使用的是B.所以我将A的导入留下了注释,并为B添加了一个导入。然后我可以将导入协议顺序恢复原状。