views:

269

answers:

3

I want to fire some code when a property is accessed and changed. I use @property... and @synthesze... 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?

+2  A: 

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.

Daniel
A: 

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.

John Franklin
You said: "In your foo and setFoo: methods..." While [obj setFoo: x] and [obj foo] are available, it is important to note that due to the modified property, obj.foo will not be available for writing, and you'll have to use obj.setFoo = x. This is not the way @property normally does it, where obj.foo is used for both reading and writing.
mahboudz
Then object.foo is equivalent to [object privateFoo], which defeats the entire purpose of using properties.
tc.
+4  A: 

You can use @property & @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.

jbrennan
FYI, your example setter has a bug, in that calling it twice with the same object can cause that object to be dealloced before it's retained. Not a really big deal, but it illustrates how difficult it can be to get these things exactly right.
Mark Bessey
I'm not sure I follow, could you explain how it should be written instead (it's not that I don't believe you, I'd like to know how to do it properly). Thanks :)
jbrennan
Oh, nvm I see the problem, I'll update it to reflect the changes.
jbrennan
another way that avoids the if statement is: [aName retain]; [name release]; name = aName;
rpetrich
Would the if statement be faster though? It's just comparing two pointers and possibly returning early. Where the alternative calls the two methods and then assigns regardless? (I know it's not really a big deal in the long run)
jbrennan