Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override all setters and getters of a subclass

I want to override the setter and getter and find the class of an objc_property_t without doing it individually for each property.

I get all the properties like so:

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; //?
    }

This is an example of how I want to override the getter and setter - if there is a better way, let me know. NSInvocation maybe?

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

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

Or is there a way to intercept all messages sent to a class?

My goal is to make a generic way to store properties of a class between launches. You probably want to ask why I don't use NSUserDefaults or NSKeyedArchiver. Well, I am using NSKeyedArchiver - I don't want to manually override every single setter and getter.

like image 954
Kevin Avatar asked Dec 18 '13 17:12

Kevin


People also ask

Can we override getter and setter in Java?

Why do we keep instance variables private? We don't want other classes to depend on them. Moreover it gives the flexibility to change a variable's type or implementation on a whim or an impulse.

Do subclasses inherit getters and setters?

Do the setter/getter methods always affect only values in objects where they are declared, even called from a subclass by inheritance? You cannot inherit the methods but not the variables. You inherit everything from the parent class. Private just means that you cannot directly access it, but it is still there.

How do you override property in Swift?

In swift to override inherited properties or methods in subclass we use override keyword which will tells the compiler to check the overriding method or property definition matches with the base class or not.


2 Answers

You can just use class_replaceMethod from the objc runtime to replace the implementation of the getter.

Example:

- (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);
}
like image 141
Ivan Genchev Avatar answered Sep 28 '22 04:09

Ivan Genchev


You can set up KVO on this and save the data on change.

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];
}
like image 40
hypercrypt Avatar answered Sep 28 '22 06:09

hypercrypt