我有一个带有委托属性的类。任何想成为代表的人都必须遵守协议。我定义了这样的一切:
#import <UIKit/UIKit.h>
@protocol TheDelegateProtocol;
@interface MyClass : UIView {
id<TheDelegateProtocol> theDelegate;
}
@property (nonatomic, assign) id<TheDelegateProtocol> theDelegate;
@end
@protocol TheDelegateProtocol<NSObject>
@required
- (void)fooBarWithFoo:(CGFloat)foo;
@end
现在疯狂的事情是:我有另一个想成为委托的班级。所以它符合该协议,如下所示:
#import <Foundation/Foundation.h>
@class MyClass; // forward declaration. importet in implementation.
@protocol TheDelegateProtocol; // need forward declaration here, right?
@interface OtherClass : NSObject <TheDelegateProtocol> {
// ivars
}
@end
我无法让它发挥作用。它说:“没有找到协议'TheDelegateProtocol'的定义”。好吧,该协议在MyClass中定义,我在实现中导入MyClass。知道那里有什么问题吗?
找出一些东西:在我尝试分配协议的方法中,它告诉我,OtherClass不符合协议。但确实如此!这是没有意义的。我还在标题中添加了协议方法....
答案 0 :(得分:4)
将协议的定义放在单独的文件中。
#import将该文件存入任何需要它的头文件。
答案 1 :(得分:4)
我认为您需要#import
定义协议的头文件。如果没有它,编译器如何知道哪些方法可用?
如果您使用另一个类(即,作为ivar或作为方法的参数),那么您可以使用前向声明。但是如果你是子类,那么你需要#import
。
答案 2 :(得分:3)
编译器的警告是正确的。 OtherClass
不符合协议,因为它没有声明协议所需的fooBarWithFoo
方法。
你试过这种方式吗?
#import "MyClass.h"
@interface OtherClass : NSObject <TheDelegateProtocol> {
// ivars
}
- (void)fooBarWithFoo:(CGFloat)foo; // <<< missing bit
@end
答案 3 :(得分:1)
他不需要声明方法符合协议。他只需要在.m文件中实现它们。
答案 4 :(得分:0)
这是警告吗?因为有时当你有循环引用和东西时会这样做,并且它会混淆,但实际上它没关系,你试过运行它看它是否有效吗?在我的项目中,我有一堆关于未找到的协议的警告,但它们在那里并且它工作正常...你可以做的是摆脱警告是尝试在类之外的其他.h文件中定义协议。你也不需要前向声明,你可以只执行它在
中定义的.h文件的#import答案 5 :(得分:0)
您的两个班级对协议的使用有所不同。 MyClass没有实现协议,它有一个属性,它是指向实现协议的类的指针。 OtherClass应该实现协议。
在定义其接口之前,其他类需要具有它继承的协议,接口和类的所有细节。因此,您需要标头中的协议在OtherClass.h中#imported
MyClass只需要知道其接口中存在的协议。
关于Stephen的回复子类化的注意事项是你不能使用类的前向声明。 (在示例中,OtherClass是NSObject的子类)
答案 6 :(得分:0)
另请参阅Apple的Communicating with Objects,其中讨论了代理,协议和选择器。