我正在尝试为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/

10-10 18:11
查看更多