Objective-C协议前向声明

ObjectProperties.h

@protocol ObjectProperties <NSObject> @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSDate *date; @property (assign, nonatomic) int64_t index; @end 

ClassA.h

 #import <Foundation/Foundation.h> @protocol ObjectProperties; @interface ClassA : NSObject <ObjectProperties> - (void)specialSauce; @end; 

ManagedClassA.h

 #import <CoreData/CoreData.h> @protocol ObjectProperties; @interface ManagedClassA : NSManagedObject <ObjectProperties> - (void)doSomething; @end; 

从上面的代码示例中,我已经定义了一个.h文件中的协议,以便与Core Data对象以及普通的ol香草对象一起使用。 看起来像“噪音”有符合类#import协议在他们的头; 如前所述,在执行文件中转发声明协议和导入会更干净。 但是,Xcode在执行此操作时会引发警告:

Cannot find protocol definition for 'ObjectProperties'

代码编译,大部分工作。 我之所以这样说,主要是因为Core Data试图为标量属性dynamic创buildgetter / setter,但我认为这可能是因为我遇到了一个边缘情况。

当然,最明显的解决办法就是将协议头导入到类头中。

如果我的理解是正确的(而且我的知识是最近获得的,所以我完全有可能是错的),如果我将协议导入到我的类头中并对协议进行了更改,那么所有后续文件类将不得不重新编译。

什么是解决这类问题的正确方法?

你不能转发声明一个超类或它符合的协议。 在这些情况下,您必须包含标题。 这是因为(在超类的情况下)超类的实例variables和方法成为你的类的一部分; 或者(在协议的情况下)协议的方法变成你的类声明的方法,而不需要明确地声明它们。 (即现在其他人包括你的类的头将会看到你的类声明这些方法,就像你自己声明的那样)。唯一可能的方法是如果它已经在这个范围内被定义,即它们的头文件被导入。

 #import <SomeClass.h> #import <SomeProtocol.h> // these two must be imported @interface MyClass : SomeClass <SomeProtocol> @end 

前向声明对于刚刚显示在variablestypes(特别是对象指针variables)中的东西是有用的。 对象指针的大小是一样的,在运行时不同types的对象指针之间没有区别(对象指针types的概念只是编译时的事情)。 所以没有必要确切地知道这些类的类是什么。 因此他们可以被宣布。

 @class SomeClass; @protocol SomeProtocol; // you can forward-declare these @interface MyClass { SomeClass *var1; id<SomeProtocol> var2; } @end 

是的你是正确的,所有的文件将需要重新编译,但这是必要的。 导入类头文件需要知道与其实现的协议相关的方法。 如果将这个定义放在.m文件中,那么它只对一个文件可见(因为.m文件永远不会被导入)。 这与前向声明类不一样。 如果您转发声明协议,则必须将其声明在与前向声明相同的范围内可见的地方。 我想不出任何例子,这不会发生在同一个文件。

在ARC中,这是一个错误,因为ARC需要知道已声明方法的内存pipe理(它们是否返回+1实例,内部指针等?)

通过在MyClass.h中声明你的类,你必须导入它的超类的所有头文件以及它在MyClass.h文件中采用的协议。 Objective-c中的协议被认为是一种不同types的inheritance。

前向声明通常用在类的成员声明中。

由于您声明与协议一致,您应该#导入包含该协议的标头。

这与#importing超类相同,而不是向前声明它:

 @class Foo; @interface Bar : Foo // Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar' @end;