Objective-C协议转发声明 [英] Objective-C Protocol Forward Declarations

查看:114
本文介绍了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对象以及普通的vanilla对象一起使用.拥有符合标准的类似乎在杂乱无章".在其标头中导入协议;向前声明协议和协议会更清洁.如上所示,导入实施文件.但是,以这种方式Xco​​de会发出警告:

From the code example above, I have defined a protocol in a .h file to be used with both Core Data objects as well as plain ol' vanilla objects. It seems like "noise" to have conforming classes ‪#import‬ the protocol in the their header; it would be cleaner to forward declare the protocol & import‬ in the implementation file as I've shown above. However, Xcode throws a warning when doing it this way:

Cannot find protocol definition for 'ObjectProperties'

该代码可以编译,并且可以正常工作.我之所以这么说,主要是因为Core Data试图动态地为标量属性创建getters/setter方法,但是我认为这可能是因为我碰到了一个极端情况.

The code compiles, and mostly works. I say mostly because there's some funkiness with Core Data trying to dynamically create the getters / setters for the scalar property, but I think that's probably because I've hit an edge case.

当然,最明显的解决方法是将协议标头导入类标头中.

Of course, the most obvious work around is to just import the protocol header into the class headers.

如果我的理解是正确的(并且我的知识是最近才获得的,那么很可能我是错的),如果我将协议导入到我的类标题中并对协议进行了更改,那么所有后续文件导入我的课程将不得不重新编译.

If my understanding is correct (and my knowledge is very recently acquired, and so it's entirely possible that I'm wrong), if I import the protocol into my class headers and make a change to the protocol, then all subsequent files that import my classes will have to be recompiled.

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

What is the correct way to do solve this type of problem?

推荐答案

您不能转发声明超类或它所遵循的协议.在这种情况下,您必须包括标题.这是因为(在超类的情况下)超类的实例变量和方法成为您的类的一部分.或(对于协议而言)协议的方法变为在您的类中声明的方法,而无需显式声明它们. (即,现在包含类标题的其他人将看到您的类声明了这些方法,就像您自己声明了这些方法一样.)唯一可能的方法是,如果它们已在此范围中定义,即导入了它们的头

You cannot forward declare a superclass or a protocol that it conforms to. In those cases, you must include the header. This is because (in the case of superclass) the superclass's instance variables and methods become part of your class; or (in the case of protocols) the protocol's methods become methods declared in your class, without needing to declare them explicitly. (i.e. Now other people who include your class's header will see that your class declares those methods, as if you declared them yourself.) The only way that that could be possible is if they were already defined in this scope, i.e. their headers are imported.

#import <SomeClass.h>
#import <SomeProtocol.h> // these two must be imported

@interface MyClass : SomeClass <SomeProtocol>
@end

对于仅以变量(特别是对象指针变量)类型显示的内容,前向声明很有用.对象指针的大小都相同,并且在运行时不同类型的对象指针之间没有区别(对象指针的类型只是编译时的事情).因此,没有真正的需要确切地知道这些类型的类中的内容.这样就可以向前声明它们.

Forward declarations are useful for things that just show up in the type of a variable (specifically, an object pointer variable). Object pointers are all the same size and there is no difference between different types of object pointers at runtime (the concept of type of object pointer is just a compile-time thing). So there is no real need to know exactly what's in the classes of those types. Thus they can be forward declared.

@class SomeClass;
@protocol SomeProtocol; // you can forward-declare these

@interface MyClass {
    SomeClass *var1;
    id<SomeProtocol> var2;
}
@end

这篇关于Objective-C协议转发声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆