覆盖子类的所有setter和getter方法

5

我希望覆盖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。


为什么不使用CoreData? - hypercrypt
  1. 对于我想要做的事情——设置和获取属性,Core Data 真的太过复杂了。
  2. 我想创建一个可重用的类,只需要最少量的设置工作。只需添加一个属性即可。
- Kevin
2个回答

6
你可以直接使用 objc runtime 中的 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);
}

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];
}

我在这里看到了这种方法 http://stackoverflow.com/questions/3374132/using-one-setter-for-all-model-ivars?rq=1,但是我想要重写getter以便我可以懒加载值。我会进行更多的尝试,谢谢。 - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接