【问题标题】:Protocol conformation error Objective C协议构象错误 Objective C
【发布时间】:2016-05-06 06:10:02
【问题描述】:

DataProvider.h

@protocol NewDataProviderProtocol 

- (void)fetchNewData;

@end

SomeClass

#import DataProvider.h
@interface SomeClass :NSObject <NewDataProviderProtocol>

@end

当我尝试使 SomeClass 符合 NewDataProviderProtocol 时,它会说,

No type or protocol named 'NewDataProviderProtocol'

这很奇怪,因为我已经导入了声明协议的标头 DataProvider.h。

所以我在 SomeClass 的接口之前转发声明 NewDataProviderProtocol 但 xcode 警告

Cannot find definition for **NewDataProviderProtocol**

这是什么原因和解决方法?

【问题讨论】:

  • 您是否也将 SomeClass.h 导入 DataProvider.h?这听起来像是一个包含循环,它会导致一个未声明的标识符。

标签: ios objective-c protocols


【解决方案1】:

A.原因

您可能有一个包含循环,因为您也将 SomeClass.h 导入 DataProvider.h。这会导致未声明的标识符。

为什么会这样?举个例子:

// Foo.h
#import "Bar.h"
@interface Foo : NSObject 
…// Do something with Bar 
@end


// Bar.h
#import "Foo.h"
@interface Bar : NSObject 
…// Do something with Foo 
@end

如果你编译,比如说 Foo.h,预编译器会扩展这个:

他得到……:

// Foo.h
#import "Bar.h"
@interface Foo : NSObject 
…// Do something with Bar 
@end

... 导入 Bar.h (并剥离 cmets ...但让我们专注于主题。)...

// Foo.h
   // Bar.h
   #import "Foo.h"
   @interface Bar : NSObject 
   …// Do something with Foo 
   @end

@interface Foo : NSObject 
…// Do something with Bar 
@end

Foo.h 不会再次被导入,因为它已经被导入了。最后:

   // Bar.h
   @interface Bar : NSObject 
   …// Do something with Foo 
   @end

@interface Foo : NSObject 
…// Do something with Bar 
@end

这很清楚:如果A依赖B,B依赖A,那么串行数据流作为一个文件,不可能同时让A在B之前,B在A之前。 (文件不是相对论的主题。)

B.解决方案

在大多数情况下,您应该给代码一个层次结构。 (有很多原因。没有进口问题是最不重要的问题之一。)在您的代码中,将 SomeClass.h 导入 DataProvider.h 看起来很奇怪。

遇到这样的问题是代码异味。尝试隔离并修复其原因。不要将代码片段移动到不同的位置以找到它工作的速度。这是抽奖。

C.结构

通常你有一个期望其他人遵守协议的类。举个例子:

// We declare the protocol here, because the class below expects from other classes to conform to the protocol.

@protocol DataSoure
…
@end

@interface Aggregator : NSObject 
- (void)addDataSource:(id<DataSource>)dataSource 
// We are using a protocol, because we do not want to restrict data sources to be subclass of a specific class.
// Therefore in this .h there cannot be an import of that – likely unknown - class
@end

SomeClass,符合协议的

#import "Aggregator.h"

@interface SomeClass:NSObject<DataSource>
…
@end

【讨论】:

  • 非常感谢。现在很清楚了。这就是原因。 :)
  • 特别是在分解代码时,我已经发生了 10923801239 次,忘记删除导入......
  • 是的,这发生在我身上,因为我之前使用了具体类并试图将其分离成一个抽象。
  • 现在这又提出了另一个问题。我们在哪里声明协议?在提供服务的类中 - SomeClass.h 或为 DataProvider.h 提供服务的类 ------ 或将其完全分离到新文件中?最佳做法是什么?
  • 您也可以将其放在单独的 .h 中。特别是。这是有道理的,如果你有一堆期望协议一致性的类。 (数据聚合器、数据选择器、数据压缩器……)
【解决方案2】:

有两件事要改变:

像这样改变定义:

@protocol NewDataProviderProtocol <NSObject>    
- (void)fetchNewData;    
@end

为什么? Why tack a protocol of NSObject to a protocol implementation

仅在 SomeClass.m 中导入 DataProvider。您始终可以在实现文件中创建SomeClass 的扩展,您可以在其中绑定协议以符合特定类。

@interface SomeClass ()<NewDataProviderProtocol>

@end

为什么?这是最好的做法。并克服前向类声明错误。例如。 Objective-C: Forward Class Declaration

【讨论】:

  • 将协议一致性转换为 .m 似乎可行。但我想不通为什么?为什么一个协议也应该符合 呢?另外我总是在 .h 文件中符合 UITableViewDataSource 为什么不能用于自定义协议?
  • @PrajeetShrestha 请查看stackoverflow.com/questions/679822/…,了解为什么您的协议应该扩展NSObject 协议。
  • @PrajeetShrestha 移动到 .m 文件对您有用,因为您的 .m 文件可能正在导入 DataProvider.h 文件。
  • 但是由于我在声明 SomeClass 的接口之前在 SomeClass.h 中导入了 DataProvider.h,它不应该在那里工作吗?
  • 它将正常工作。但我指的是未来的问题(?),它不是必需的,但它是一个很好的做法:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
相关资源
最近更新 更多