考虑这个课程:CAEmitterLayer
。此类响应属性name
。
现在我创建了一个名为CAEmitterLayer
的{{1}},这个类符合我创建的名为MyEmitter
的协议。
MyProtocol
类声明是这样的:
标题
MyEmitter
实施
#import "MyProtocol.h"
@interface MyEmitter : CAEmitterLayer <MyProtocol>
@end
并且协议就是这样:
#import "MyEmitter.h"
@implementation MyEmitter
@synthesize internalString = _internalString;
@end
这就是问题所在。如果我像这样创建一个新对象
@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString * internalString;
@end
并尝试使用MyEmitter *obj = [[MyEmitter alloc] init];
属性,xcode抱怨没有已知的选择器'name'实例方法
实际上我无法访问类name
中的任何属性,即使CAEmitterLayer
是该类的子类。
我试图像这样使用它:
MyEmitter
显然协议隐藏了超类中的所有内容。为什么这样,我该如何解决?
注意:我必须将该合成行添加到该类中,否则xcode不会停止抱怨。
答案 0 :(得分:4)
node
的静态类型为id <MyProtocol>
。编译器正确地说这种类型没有声明setName:
方法。
只需切换到MyEmitter *
即可。
答案 1 :(得分:2)
要扩展另一个答案,您收到编译时错误,因为编译器必须按照您所说的那样工作。
现在,您知道(或者至少希望)node
在运行时将成为MyEmitter
的实例,但编译器没有,因为您告诉它node
1}}是id <MyProtocol>
。
如果你可以让程序运行,那么[node setName:]
就可以了,因为objective-C在运行时找到了正确的选择器。
同样如果你告诉编译器node
是MyEmitter
的一个实例,但在运行时它是一个不同的对象类(由于你的代码中的其他地方出现了错误)然后它会编译但是可能会在运行时抛出异常。
所以你可以说 -
for (MyEmitter *node in nodes) {
[node setName:@"ddd"];
}
或者,如果您不需要执行特定于您的子类的任何操作,您甚至可以说
for (CAEmitterLayer *node in nodes) {
[node setName:@"ddd"];
}