Question

I want to fire some code when a property is accessed and changed. I use @property and @synthesize in my code for my ivars. The properties are retained, so I'd like to keep that memory management stuff automatically generated by @synthesize.

However, I assume that @synthesize tells the compiler to generate the accessor methods code right where @synthesize is, so most of the cases at the top of the code, right?

And when I have a property foo, I get -setFoo and -foo methods. Could I then just make a method like this, to execute some more custom code when a property is changed?

-(void)setFoo {
    // custom stuff
}

Now that's a problem. How to execute the first one? I wouldn't love to have a different name here. Is there maybe a way to let the @synthesize directive create other names for getter and setter methods, which I then call easily? And I would still be able to use the dot syntax then to access them?

Was it helpful?

Solution

You can use @property and @synthesize just like you normally would, but provide a custom setter or getter (or both) and those will be used instead. Typically I will do something like this:

// Override the setter
- (void)setName:(NSString *)aName
{
    if (name == aName)
        return;

    [name release];
    name = [aName retain];

    //custom code here
}

When I use the set property, it will invoke my custom method. However, the get will still be synthesized.

OTHER TIPS

If you provide an implemnetation for the setters or getters it will use that instead of the generated implementation. Its not hard to implement the "retaining" aspect of the getters and setters that are generated for you by the compiler when u synthesize, so you can just write your own getters and setters i would say and go with that.

One wacky solution is to create an abstract super class that does gives you the normal property synthesis. Then create a concrete subclass that you will actually use, and that simply implements and override method (same signature) and calls super to do the actual setting. This allows you to do whatever you want to do before or after the call to super's implementation.

Example:

@interface ALTOClassA : NSObject


@property NSString *catName;

@end

Nothing else needed in the .m beyond the stubbed file for this test.

Create the subclass, nothing needed specially in the @interface

#import "ALTOClassA.h"

@interface ALTOClassAJunior : ALTOClassA

@end

In the @implementation we do our override.

#import "ALTOClassAJunior.h"

@implementation ALTOClassAJunior


- (void)setCatName:(NSString*)aCatName {
    NSLog(@"%@",NSStringFromSelector(_cmd));
    [super setCatName:aCatName];
    NSLog(@"after super: self.catName %@", self.catName);
}
@end

In use:

    ALTOClassAJunior *aCAJ = [ALTOClassAJunior new];
NSLog(@"aCAS.catName %@", aCAJ.catName);

NSLog(@"set it to George.");

[aCAJ setCatName:@"George"];

NSLog(@"aCAS.catName %@", aCAJ.catName);

This allows you to leverage the autogenerated code, and still do stuff you want to do with your class. Abstract Super Class is often a useful solution for many things.

Yes, in your @property declaration, you can specify the getter and setter methods.

@property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo;

In your foo and setFoo: methods, call [self privateGetFoo] or [self privateSetFoo:f] then your custom code.

The object can also set an observer on itself with addObserver:forKeyPath:options:context:.

That said, I don't think either of these are very clean ways to do things. Better to write your own getter/setter as others have suggested.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top