Dan K.
Dan K.

Reputation: 1532

Is it possible to customize @synthesized properties?

I'm probably just being a bit lazy here, but bear with me. Here's my situation. I have a class with two nonatomic, retained properties. Let's say:

@property (nonatomic, retain) UITextField *dateField;
@property (nonatomic, retain) NSDate *date;

I synthesize them as expected in the implementation. What I want to happen is that whenever the setter on date is invoked, it also does something to the dateField (i.e. it sets the text property on the dateField to be a nicely formatted version of the date).

I realize I can just manually override the setter for date in my implementation by doing the following:

- (void) setDate:(NSDate *)newDate {
    if (date != newDate) {
        [date release];
        date = [newDate retain];
        // my code to touch the dateField goes here
    }
}

What would be awesome is if I could let Objective C handle the retain/release cycle, but still be able to "register" (for lack of a better term) a custom handler that would be invoked after the retain/release/set happens. My guess is that isn't possible. My google-fu didn't come up with any answer to this, though, so I thought I'd ask.

Upvotes: 4

Views: 208

Answers (2)

justin
justin

Reputation: 104698

you may accomplish by creating a private ivar/property (ok, you have to document a property is private, ideally using an obvious name) with another name:

@property (nonatomic, retain) UITextField *dateField;
@property (nonatomic, retain) NSDate *date; // interface only
@property (nonatomic, retain) NSDate *datePRIVATE; // the real ivar.
...
@synthesize datePRIVATE;
- (void)setDate:(NSDate *)newDate {
    self.datePRIVATE = newDate;
    [self.dateField updateDisplayedDate:self.datePRIVATE];
}

Upvotes: 0

Mike Morearty
Mike Morearty

Reputation: 10273

KVO (key/value observing) can do this, sort of, but it would end up being even more code, and probably no easier to read or to write.

You may be familiar with KVO, but in case you (or others) aren't: In your init function, you would do this:

[self addObserver:self forKeyPath:@"date" options:0 context:NULL];

Then you would implement this:

-(void)observeValueForKeyPath:(NSString*)keyPath 
                     ofObject:(id)object
                       change:(NSDictionary*)change
                      context:(void*)context
{
    if (object == self && [keyPath isEqualToString:@"date"]) {
        // code to touch the dateField goes here
    }
}

Finally, in dealloc, you would do this:

[self removeObserver:self forKeyPath:@"date"];

As you can see, that's even more code, and harder to understand. Not really very effective for someone whose goal is to be lazy :-) But KVO is the main "data binding" functionality of Objective-C. There are some platforms (e.g. Flex) which can do data binding with a whole lot less code, but it takes a lot of work in Objective-C.

By the way, not a big deal, but the sample code you showed is buggy -- it should probably look more like this:

- (void) setDate:(NSDate *)newDate {
    if (date != newDate) {
        [date release];
        date = [newDate retain];
        // my code to touch the dateField goes here
    }
}

Upvotes: 4

Related Questions