1

I have one class called dog and another class called cat.

Dog has an variable, "name" declared with @property in the .h file.

In the cat class, I have set the name by using the command, myDog.name = "buster", after creating the variable "myDog" of type dog.

I would like to do additional operations when the name is set by overriding the set method normally created by the @synthesize command.

How can I do that? Thanks for the help!

Andrew
  • 3,901
  • 15
  • 50
  • 64
  • "Override" isn't really the right term here. If you implement a property accessor, the compiler will use your implementation even if you used the @synthesize directive for that property. This is useful if you want to have the compiler provide, say, the getter but you still want to provide the setter. You can, of course, override synthesized accessors from a subclass. – Caleb Jun 27 '11 at 13:07
  • Do you want to *get all the benefits* of synthesized methods and **add your own logic** to them, or do you want to replace them entirely and rely all on your own logic (setter + additional)? For the latter Perception's and Chance Hudson's answers do well. If you however want to make use of all the underlying optimizations as (potentially) done by Apple's `@synthesize`, then you'd have to follow steps as such from my (now updated) answer. Your question is a bit ambiguous. – Regexident Jun 27 '11 at 13:12
  • 1
    @Caleb: I just added a workaround for (kind of) overriding synthesized methods from within the same class. This is how Apple should have implemented them in first place, imho. with `.foo` just being a forward declaration for `.primitiveFoo` by default. Kind of like how CoreData/mogenerator does things. – Regexident Jun 27 '11 at 13:15
  • possible duplicate of [Objective-C synthesize property name overriding](http://stackoverflow.com/questions/3802851/objective-c-synthesize-property-name-overriding) – Gilles 'SO- stop being evil' Jun 27 '11 at 13:23
  • 1
    @Gilles: if you read OP's question closely (and Caleb's and my comments) it's actually not a duplicate. Your linked answer simply overrides (as in replace in total) a synthesized method. It doesn't extend its existing logic in any way. – Regexident Jun 27 '11 at 13:49
  • 1
    @Regexident: the whole primitive thing seems like a lot of bother. The main benefit of synthesized accessors that you miss out on if you provide your own accessor is the compiler providing the accessor for you. But if you're planning on providing the accessor anyway, this isn't a big loss -- it's really not that hard to write a setter that properly retains its contents. – Caleb Jun 27 '11 at 14:32

3 Answers3

5

All you have to do is leave the @synthesize then create whichever methods you want to be custom. Example:

In .h

@property(nonatomic, retain)NSString *Bob;

In .m

@synthesize bob;

-(void)setBob:(NSString *)bobValue{
    [bobValue retain];
    [bob release];
    bob = bobValue;
    //your custom stuffs here
}
Chance Hudson
  • 2,849
  • 1
  • 19
  • 22
  • 1
    llvm complains about overriding a `@synthesize`d method. Also, you meant `autorelease`; otherwise there is a race condition to use a `release`d value of `bob`. – Richard Jun 27 '11 at 12:42
  • Also this basically makes the `@synthesize` useless (for the setter at least). Further more it won't bring you any of the magic that `@synthesize` provides for free, instead introduces additional code/logic to maintenance. You're basically stepping back into Objective-C 1.0. – Regexident Jun 27 '11 at 12:48
  • Ok, as for the memory management, i was just providing a rough example. @Regexident the asker was looking for a way to implement custom code when he sets the value of his property, and this is how to do it, even if it is overriding some ObjC magic. As for llvm complaining, i guess you could just implement both getters and setters and remove the @synthesize. I thought you could just override one and it would fill in the other, but i guess not :-( – Chance Hudson Jun 27 '11 at 12:54
  • OP's talking about **extending** those `@synthesized` methods though, not **replacing** them, isn't he? *"[…]I would like to do additional operations when the name is set[…]"* – Regexident Jun 27 '11 at 13:20
  • Hmm, i understood it as him wanting to add additional functionality to setting his variables. Wouldn't this be the same as extending it if he added his own custom code to it? – Chance Hudson Jun 27 '11 at 13:27
  • You could also extend class X by reimplementing it, no? ;) That's replacing though, not real extending. ;) Keep in mind that there's potentially much more happening in synthesized methods (which ultimatively is up to speculation, due to their opaqueness) that one would think: http://stackoverflow.com/questions/3925725/viewing-the-code-generated-by-synthesize-for-getter-setter/3957019#3957019 – Regexident Jun 27 '11 at 13:44
3

This has been pretty much answered on SO already - see Objective-C synthesize property name overriding for details. In particular, @Dev Kanchen's answer which includes example code.

Community
  • 1
  • 1
Perception
  • 79,279
  • 19
  • 185
  • 195
  • That is what I was looking for, but isn't that just recursive? – Andrew Jun 27 '11 at 12:46
  • No its not. The compiler basically skips synthesizing your setter method, since you are explicitly providing one. Also, you will notice that nowhere in the body of your setter is the setter itself called - you are merely assigning the function variable to the property yourself. As a side note, you can run into some issues if you are using the atomic keyword for your property. Please read more on that here: http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties. – Perception Jun 27 '11 at 12:56
  • You're replacing the synthesized name property method, not extending it, though, which if I'm not mistaken, is what OP is actually looking for. `@synthesize + own logic`, not `solely own logic`. – Regexident Jun 27 '11 at 13:18
  • I read it as 'I want to set the property + do additional stuff'. But all the additional conversation has definitely been interesting and imo, worthwile. – Perception Jun 28 '11 at 20:12
1

You cannot override (and call it within) a synthesized method from within the very same class.

You can however override it from a subclass (or rather: synthesize it in an abstract superclass).

If you simply want to perform additional (vs. different) operations upon property change I would use KVO by simply adding each dog as observer to its own "name" property in -(id)init;.


Edit:

There is a way to add additional logic to synthesized methods from within the same class:
Define a private intermediate property in a class extension.

I've attached source code for a class which uses synthesized properties and takes care(sic!) of keeping the dog's owner in sync with its own identity.

Dog.h:

#import <Foundation/Foundation.h>

@interface Dog : NSObject {
@private
    NSString *name;
    NSString *owner;
}

@property (nonatomic, readwrite, retain) NSString *name;
@property (nonatomic, readwrite, retain) NSString *owner;

@end

Dog.m:

#import "Dog.h"

@interface Dog ()

@property (nonatomic, readwrite, retain) NSString *primitiveName;

@end

@implementation Dog

@dynamic name;

@synthesize primitiveName = name;
@synthesize owner;

- (id)init {
    if ((self = [super init])) {
        name = @"Snowy";
        owner = @"Tintin";
    }

    return self;
}

- (void)dealloc {
    [super dealloc];
}

- (NSString *)name {
    return self.primitiveName;
}

- (void)setName:(NSString *)aName {
    self.primitiveName = aName;
    if ([aName isEqualToString:@"Snoopy"]) {
        self.owner = @"Charlie Brown";
    }
    else if ([aName isEqualToString:@"Snowy"]) {
        self.owner = @"Tintin";
    }
}

- (NSString *)description {
    return [NSString stringWithFormat:@"<%@ name:'%@' owner:'%@'>", [self class], self.name, self.owner];
}

@end

Test:

Dog *dog = [[Dog alloc] init];
NSLog(@"%@", dog);
dog.name = @"Snoopy";
NSLog(@"%@", dog);
dog.name = @"Snowy";
NSLog(@"%@", dog);

Result:

<Dog name:'Snowy' owner:'Tintin'>
<Dog name:'Snoopy' owner:'Charlie Brown'>
<Dog name:'Snowy' owner:'Tintin'>
Regexident
  • 29,441
  • 10
  • 93
  • 100
  • In the split view application that apple offers, it seems that they have overridden the "set" method when the app is using core data. How might they have done that? – Andrew Jun 27 '11 at 12:38
  • Well, you can of course override a synthesized method. What you cannot do however is just overriding it and calling its synthesized version right within, which if I'm not mistaken is basically what you'd want to do, right? – Regexident Jun 27 '11 at 12:46