我正在尝试为NSCODER协议创建一个通用的实现。
代码将包装在一个宏中,该宏将实现nscoding。
为了实现协议,我们需要两个功能:
-(void)encodeWithCoder:(NSCoder*)coder;
-(id)initWithCoder:(NSCoder*)coder;
iNITWORKCONDER函数的通用实现将是:
-(id)initWithCoder:(NSCoder*)coder {
if ([super conformsToProtocol:@protocol(NSCoding)])
self = [super initWithCoder:coder];
else {
self = [super init];
}
if (!self) return self;
self = [MyGenericCoder initWithCoder:coder forObject:self withClass:[__clazz class]];
return self;
}
有问题的一行是
self = [super initWithCoder:coder];
它不会编译,因为当我们在一个类中使用时,super没有响应initWithCoder:
,而它的super没有实现nscoding。将super强制转换为NSObject<NSCoding>*
不适用于llvm编译器。[super performSelector:(initWithCoder:) withObject:coder]
也不会工作,因为super==self,这将导致无限循环。如何调用
[super initWithCoder:coder]
的方式来触发超类中的函数,不会生成编译警告/错误? 最佳答案
您可以使用+instancesRespondToSelector:
来确定您的超类是否响应选择器,然后直接使用objc_msgSendSuper()
来实际调用它。
#import <objc/message.h>
- (id)initWithCoder:(NSCoder *)coder {
// Note: use [__clazz superclass] directly because we need the
// compile-time superclass instead of the runtime superclass.
if ([[__clazz superclass] instancesRespondToSelector:_cmd]) {
struct objc_super sup = {self, [__clazz superclass]};
((id(*)(struct objc_super *, SEL, NSCoder*))objc_msgSendSuper)(&sup, _cmd, coder);
} else {
[super init];
}
if (!self) return self;
self = [MyGenericCoder initWithCoder:coder forObject:self withClass:[__clazz class]];
return self;
}
关于objective-c - 在父类(super class)中调用可选方法(Objective-C),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12095984/