覆盖子类的所有setter和getter

时间:2013-12-18 17:27:48

标签: objective-c getter-setter

我想覆盖setter和getter并找到objc_property_t的类,而不是为每个属性单独执行它。

我得到了所有的属性:

unsigned int numberOfProperties;
    objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
    for (NSUInteger i = 0; i < numberOfProperties; i++) {
        objc_property_t property = propertyArray[i];
        NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];

        property.getter = SEL; //?
    }

这是我想要覆盖getter和setter的示例 - 如果有更好的方法,请告诉我。 NSInvocation可能吗?

- (UIImage *)backgroundImage
{
    return [self overrideGetterWithSelector:NSStringFromSelector(_cmd)];
}

- (void)setBackgroundImage:(UIImage *)backgroundImage
{
    [self overrideSetterForObject:backgroundImage forSelector:NSStringFromSelector(_cmd)];
}

或者有没有办法拦截发送给班级的所有邮件?

我的目标是制作一种在启动之间存储类属性的通用方法。您可能想问我为什么不使用NSUserDefaultsNSKeyedArchiver。好吧,我正在使用NSKeyedArchiver - 我不想手动覆盖每一个setter和getter。

2 个答案:

答案 0 :(得分:6)

您可以使用objc运行时中的class_replaceMethod来替换getter的实现。

示例:

- (void)replaceGetters {
    unsigned int numberOfProperties;
    objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
    for (NSUInteger i = 0; i < numberOfProperties; i++) {
        objc_property_t property = propertyArray[i];
        const char *attrs = property_getAttributes(property);
        NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];

        // property.getter = SEL; //?
        // becomes
        class_replaceMethod([self class], NSSelectorFromString(name), (IMP)myNewGetter, attrs);
    }
}

id myNewGetter(id self, SEL _cmd) {
    // do whatever you want with the variables....

    // you can work out the name of the variable using - NSStringFromSelector(_cmd)
    // or by looking at the attributes of the property with property_getAttributes(property);
    // There's a V_varName in the property attributes
    // and get it's value using - class_getInstanceVariable ()
    //     Ivar ivar = class_getInstanceVariable([SomeClass class], "_myVarName");
    //     return object_getIvar(self, ivar);
}

答案 1 :(得分:2)

您可以在此设置KVO并在更改时保存数据。

static const void *KVOContext = &KVOContext;

unsigned int numberOfProperties;
objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
for (NSUInteger i = 0; i < numberOfProperties; i++)
{
    objc_property_t property = propertyArray[i];
    NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];
    [self addObserver:self forKeyPath:name options:kNilOptions context:KVOContext];
}