【问题标题】:Cannot find protocol declaration找不到协议声明
【发布时间】:2011-09-20 19:30:30
【问题描述】:

我有两个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

【问题讨论】:

  • 也许您可以发布一些相关代码(精简以显示您定义的内容)。
  • 我刚刚发布了一些。缩进很奇怪 - 抱歉!
  • 以后可以使用顶部的{} 按钮来封装代码,或者使用反引号手动格式化。
  • 按照@TwistedUmbrella 的说明,我遇到了同样的问题并解决了。
  • 检查您包含的文件。
    这是两个相互包含的标头的症状。
    有时会导致此错误。

标签: objective-c cocoa-touch protocols


【解决方案1】:

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

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 行尝试使用它们之前声明适当的协议。

【讨论】:

  • 感谢您的精彩解释!对于任何想要一些清晰的例子来说明这与 Storyboard、SplitViews 等的关系... Tim Roadley 在 www.timroadley.com 上有一些出色的教程(我认为这是正确的地址...)。我是从那些页面被引导到这里的。
  • 我本来打算 +1 的,但是因为它有 42 个赞,而 42 是宇宙的秘密,这就是宇宙的秘密,我就把这个留在这里。
  • 太好了,我一直在寻找这种答案!
【解决方案2】:

在#import 行上方编写协议声明代码 例如

@protocol -----

@结束

进口----

@interface 类名---

【讨论】:

  • thanx...它对我有用..但我不知道如何。你能解释一下吗?
  • 3小时后,你救了我的命!!你能解释一下吗?谢谢
  • 如果时间允许,请阅读 Anomie 的回答,以进一步了解可能发生的情况。将协议置于导入之上,确保在评估导入之前定义协议。这个问题类似于循环类依赖。强烈建议 Anomie 建议将您的代表分成自己的文件。
  • 检查您包含的文件。这是两个相互包含的标头的症状。有时它会导致此错误。
  • 非常感谢。这让我很恼火,但迫使你提前声明协议,我从你们所说的话中收集到。但是,当您查看标头时,它会更有意义,因为您将其分成两部分,协议以及它们从顶部整齐的来源。非常感谢,这对我有用,从现在开始我将把它作为一种常见的做法。
【解决方案3】:

我遇到了几乎相同的问题,感谢上面的答案,我解决了这个问题,但方式略有不同。

我所做的只是将#import 行放在 头文件中的协议声明之后。 希望我能帮上忙。如果有人知道由于某种原因这是不好的编程,请告诉我

【讨论】:

  • 在阅读了其他答案后,我试了一下这个想法。当两个标头相互导入时,它似乎会创建一个循环导入。在带有协议的标头中,将调用协议的标头的导入移到协议声明下方是一个完美的解决方案。
【解决方案4】:

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

基本上,您只需将 &lt;YourProtocolName&gt; 从 .h 类文件移动到 .m 文件中的类扩展名

所以在你的 .m 文件中添加

@interface YourClassName () <YourProtocolName>
@end

我不知道这是否真的是一个好习惯,但它看起来是一个避免导入周期的更清洁的解决方案。

【讨论】:

    【解决方案5】:

    尝试将 放在实现文件而不是头文件中。它会起作用的。

    【讨论】:

    • 这个。 StackOverflow 周围的任何其他线程中没有其他答案解决了我的情况,除了那个。谢谢。
    【解决方案6】:

    我在导入之前遵循了移动协议的修复方法,它解决了问题...导入包括委托,因此导致了问题。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-07
      • 2013-06-30
      相关资源
      最近更新 更多